Photo by Van Tay Media / Unsplash

De Ruby à Rust

code 13 févr. 2026

Philosophies fondamentales

Deux objectifs distincts

Points communs et concepts partagés

Malgré leurs philosophies différentes, Ruby et Rust partagent des concepts modernes qui facilitent la transition de l'un à l'autre.

Les grandes différences structurelles

Les différences fondamentales expliquent leurs cas d'usage respectifs.

La cohérence d’apprentissage

Du prototypage à la production

Similitudes du code

Similitudes dans le langage et la syntaxe

Traits (Rust) vs Modules/Mixins (Ruby)

Focus : Syntaxe des blocs et closures

Blocs avec paramètres

ruby

# Ruby
numbers.map { |x| x * 2 }
numbers.select { |x| x > 5 }
rust

// Rust
numbers.iter().map(|x| x * 2)
numbers.iter().filter(|&x| x > 5)

Blocs multi-lignes

ruby

# Ruby
items.each do |item|
    puts item.name
    item.process
end
rust

// Rust
items.iter().for_each(|item| {
    println!("{}", item.name);
    item.process();
});

Pattern matching

Voir vidéo et Post

Puissance et principe du case en Ruby
En Ruby le statement case est capable de proposer de multiple usages Usage générique def test(x) case x when 1..5 “valeur entre 1 et 5” when 6 “valeur = à 6″ when “foo”, “bar” “soit foo ou bar” when /test/ “c’est un test” when String “c’est une String” else

Match sur valeurs

ruby

# Ruby (depuis 2.7)
case value
in 0
  "zero"
in 1..10
  "small"
in x if x > 100
  "big"
end
rust

// Rust
match value {
    0 => "zero",
    1..=10 => "small",
    x if x > 100 => "big",
    _ => "other"
}

Destructuration

ruby

# Ruby
case point
in {x: 0, y: 0}
  "origin"
in {x: x, y: 0}
  "on x-axis at #{x}"
end
rust

// Rust
match point {
    Point { x: 0, y: 0 } => "origin",
    Point { x, y: 0 } => format!("on x-axis at {}", x),
    _ => "somewhere else"
}

Méthodes chaînées et programmation fonctionnelle

Transformations de collections

ruby

# Ruby
numbers
  .select { |x| x.even? }
  .map { |x| x * 2 }
  .sum
rust

// Rust
numbers
    .iter()
    .filter(|&x| x % 2 == 0)
    .map(|x| x * 2)
    .sum()

Opérations complexes

ruby

# Ruby
users
  .group_by(&:department)
  .transform_values { |users| users.map(&:salary).sum }
rust

// Rust
users
    .iter()
    .into_group_map_by(|user| &user.department)
    .into_iter()
    .map(|(dept, users)| (dept, users.iter().map(|u| u.salary).sum()))
    .collect()

Itérateurs et énumération

Création et utilisation d'itérateurs

ruby

# Ruby
(1..10)
  .lazy
  .map { |x| x * x }
  .select { |x| x > 20 }
  .first(3)
rust

// Rust
(1..=10)
    .map(|x| x * x)
    .filter(|&x| x > 20)
    .take(3)
    .collect::<Vec<_>>()

Itération avec index

ruby

# Ruby
items.each_with_index do |item, index|
  puts "#{index}: #{item}"
end
rust

// Rust
items.iter().enumerate().for_each(|(index, item)| {
    println!("{}: {}", index, item);
});

Conventions de nommage

Snake case

ruby

# Ruby
def calculate_total_price(items)
  base_price = items.sum(&:price)
  tax_amount = base_price * TAX_RATE
  base_price + tax_amount
end
rust

// Rust
fn calculate_total_price(items: &[Item]) -> f64 {
    let base_price: f64 = items.iter().map(|item| item.price).sum();
    let tax_amount = base_price * TAX_RATE;
    base_price + tax_amount
}

Gestion des collections

Création et manipulation

ruby

# Ruby
hash = { name: "John", age: 30 }
hash[:email] = "john@example.com"
hash.each { |k, v| puts "#{k}: #{v}" }
rust

// Rust
use std::collections::HashMap;

let mut hash = HashMap::new();
hash.insert("name", "John");
hash.insert("age", "30");
hash.insert("email", "john@example.com");
hash.iter().for_each(|(k, v)| println!("{}: {}", k, v));

Gestion des modules et namespaces

Organisation du code

ruby

# Ruby
module Authentication
  class User
    def authenticate(password)
      # ...
    end
  end
end
rust

// Rust
mod authentication {
    pub struct User {
        // fields
    }
    
    impl User {
        pub fn authenticate(&self, password: &str) -> bool {
            // ...
        }
    }
}

Tests intégrés

Tests unitaires

ruby

# Ruby
require 'minitest/autorun'

class TestCalculator < Minitest::Test
  def test_addition
    assert_equal 4, Calculator.add(2, 2)
  end
end
rust

// Rust
#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_addition() {
        assert_eq!(Calculator::add(2, 2), 4);
    }
}

Ces similitudes syntaxiques facilitent grandement la transition entre les deux langages, même si les concepts sous-jacents (ownership, borrowing en Rust vs garbage collection en Ruby) sont très différents.

Différences du code

Gestion des erreurs et Options

Valeurs optionnelles

ruby

# Ruby
def find_user(id)
  users.find { |u| u.id == id }
end

user = find_user(123)
puts user&.name || "Unknown"
rust

// Rust
fn find_user(id: u32) -> Option<&User> {
    users.iter().find(|u| u.id == id)
}

let user = find_user(123);
println!("{}", user.map_or("Unknown".to_string(), |u| u.name.clone()));

Chaînage avec gestion d'erreur

ruby

# Ruby
result = fetch_data(id)
  &.then { |data| process_data(data) }
  &.then { |processed| save_data(processed) }
rust

// Rust
let result = fetch_data(id)
    .and_then(|data| process_data(data))
    .and_then(|processed| save_data(processed));

Métaprogrammation et macros

Génération de code

ruby

# Ruby
[:name, :email, :phone].each do |attr|
  define_method("#{attr}_present?") do
    !send(attr).nil? && !send(attr).empty?
  end
end
rust

// Rust
macro_rules! generate_presence_check {
    ($($field:ident),*) => {
        $(
            fn paste::paste! { [<$field _present>] }(&self) -> bool {
                !self.$field.is_empty()
            }
        )*
    };
}

Définition et structures de classes

ruby

# Ruby
class Point
  attr_accessor :x, :y
  
  def initialize(x, y)
    @x, @y = x, y
  end
  
  def distance_from_origin
    Math.sqrt(x**2 + y**2)
  end
end
rust

// Rust
struct Point {
    x: f64,
    y: f64,
}

impl Point {
    fn new(x: f64, y: f64) -> Self {
        Point { x, y }
    }
    
    fn distance_from_origin(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

Similitude des outils

Similitudes dans les outils de développement

Détails des outils de développement


Comparaison complète : Ruby vs Rust pour le développement de bibliothèques

Structure des projets

Ruby (Gem)

simple_calculator/
├── lib/
│   ├── simple_calculator.rb
│   ├── simple_calculator/
│   │   ├── calculator.rb
│   │   └── converter.rb
├── spec/
│   ├── spec_helper.rb
│   ├── simple_calculator_spec.rb
│   ├── simple_calculator/
│   │   ├── calculator_spec.rb
│   │   └── converter_spec.rb
├── .yardopts
├── Gemfile
├── Rakefile
├── simple_calculator.gemspec
└── README.md

Rust (Crate)

simple_calculator/
├── src/
│   ├── lib.rs
│   ├── calculator.rs
│   └── converter.rs
├── tests/
│   └── integration_tests.rs
├── Cargo.toml
├── Cargo.lock
└── README.md

Code source

Ruby (Gem)

lib/simple_calculator.rb

require "simple_calculator/calculator"
require "simple_calculator/converter"

# A simple calculator library for basic operations and conversions
#
# @example Basic usage
#   SimpleCalculator.add(2, 3)       # => 5
#   SimpleCalculator.subtract(5, 3)  # => 2
#
# @example Temperature conversion
#   SimpleCalculator.celsius_to_fahrenheit(0)  # => 32
module SimpleCalculator
  VERSION = "0.1.0"
  
  # Adds two numbers
  #
  # @param a [Numeric] First number
  # @param b [Numeric] Second number
  # @return [Numeric] Sum of a and b
  # @raise [TypeError] If arguments are not numeric
  def self.add(a, b)
    Calculator.new.add(a, b)
  end
  
  # Subtracts second number from first
  #
  # @param a [Numeric] First number
  # @param b [Numeric] Second number
  # @return [Numeric] Result of a - b
  # @raise [TypeError] If arguments are not numeric
  def self.subtract(a, b)
    Calculator.new.subtract(a, b)
  end
  
  # Converts Celsius to Fahrenheit
  #
  # @param celsius [Numeric] Temperature in Celsius
  # @return [Numeric] Temperature in Fahrenheit
  # @raise [TypeError] If argument is not numeric
  def self.celsius_to_fahrenheit(celsius)
    Converter.new.celsius_to_fahrenheit(celsius)
  end
end

lib/simple_calculator/calculator.rb

module SimpleCalculator
  # Performs basic arithmetic operations
  class Calculator
    # Adds two numbers
    #
    # @param a [Numeric] First number
    # @param b [Numeric] Second number
    # @return [Numeric] Sum of a and b
    # @raise [TypeError] If arguments are not numeric
    def add(a, b)
      validate_numbers(a, b)
      a + b
    end
    
    # Subtracts second number from first
    #
    # @param a [Numeric] First number
    # @param b [Numeric] Second number
    # @return [Numeric] Result of a - b
    # @raise [TypeError] If arguments are not numeric
    def subtract(a, b)
      validate_numbers(a, b)
      a - b
    end
    
    private
    
    # Validates that arguments are numeric
    #
    # @param a [Object] First object to check
    # @param b [Object] Second object to check
    # @raise [TypeError] If arguments are not numeric
    def validate_numbers(a, b)
      raise TypeError, "Arguments must be numbers" 
             unless a.is_a?(Numeric) && b.is_a?(Numeric)
    end
  end
end

lib/simple_calculator/converter.rb

module SimpleCalculator
  # Performs temperature conversions
  class Converter
    # Converts Celsius to Fahrenheit
    #
    # @param celsius [Numeric] Temperature in Celsius
    # @return [Numeric] Temperature in Fahrenheit
    # @raise [TypeError] If argument is not numeric
    def celsius_to_fahrenheit(celsius)
      raise TypeError, "Argument must be a number" 
             unless celsius.is_a?(Numeric)
      (celsius * 9.0/5.0) + 32
    end
  end
end

Rust (Crate)

src/lib.rs

//! A simple calculator library for basic operations and conversions
//!
//! # Examples
//!
//! ```
//! // Basic usage
//! use simple_calculator::{add, subtract};
//! assert_eq!(add(2.0, 3.0), 5.0);
//! assert_eq!(subtract(5.0, 3.0), 2.0);
//!
//! // Temperature conversion
//! use simple_calculator::celsius_to_fahrenheit;
//! assert_eq!(celsius_to_fahrenheit(0.0), 32.0);
//! ```

pub mod calculator;
pub mod converter;

// Re-export main functionality
pub use calculator::Calculator;
pub use converter::Converter;

// Define custom error type
use thiserror::Error;

/// Errors that can occur in calculator operations
#[derive(Error, Debug)]
pub enum CalculatorError {
    /// Indicates an invalid input was provided
    #[error("Invalid input: {0}")]
    InvalidInput(String),
}

/// Adds two numbers
///
/// # Examples
///
/// ```
/// use simple_calculator::add;
/// assert_eq!(add(2.0, 3.0), 5.0);
/// ```
pub fn add(a: f64, b: f64) -> f64 {
    Calculator::new().add(a, b)
}

/// Subtracts the second number from the first
///
/// # Examples
///
/// ```
/// use simple_calculator::subtract;
/// assert_eq!(subtract(5.0, 3.0), 2.0);
/// ```
pub fn subtract(a: f64, b: f64) -> f64 {
    Calculator::new().subtract(a, b)
}

/// Converts a temperature from Celsius to Fahrenheit
///
/// # Examples
///
/// ```
/// use simple_calculator::celsius_to_fahrenheit;
/// assert_eq!(celsius_to_fahrenheit(0.0), 32.0);
/// assert_eq!(celsius_to_fahrenheit(100.0), 212.0);
/// ```
pub fn celsius_to_fahrenheit(celsius: f64) -> f64 {
    Converter::new().celsius_to_fahrenheit(celsius)
}

src/calculator.rs

use crate::CalculatorError;

/// A calculator for basic arithmetic operations
pub struct Calculator;

impl Calculator {
    /// Creates a new calculator
    pub fn new() -> Self {
        Calculator
    }
    
    /// Adds two numbers
    ///
    /// # Examples
    ///
    /// ```
    /// use simple_calculator::Calculator;
    /// let calc = Calculator::new();
    /// assert_eq!(calc.add(2.0, 3.0), 5.0);
    /// ```
    pub fn add(&self, a: f64, b: f64) -> f64 {
        a + b
    }
    
    /// Subtracts the second number from the first
    ///
    /// # Examples
    ///
    /// ```
    /// use simple_calculator::Calculator;
    /// let calc = Calculator::new();
    /// assert_eq!(calc.subtract(5.0, 3.0), 2.0);
    /// ```
    pub fn subtract(&self, a: f64, b: f64) -> f64 {
        a - b
    }
    
    /// Divides the first number by the second, returning an error if
    /// the divisor is zero
    ///
    /// # Examples
    ///
    /// ```
    /// use simple_calculator::Calculator;
    /// let calc = Calculator::new();
    /// assert_eq!(calc.safe_divide(6.0, 2.0).unwrap(), 3.0);
    /// assert!(calc.safe_divide(6.0, 0.0).is_err());
    /// ```
    pub fn safe_divide(&self, a: f64, b: f64) -> Result<f64, CalculatorError> {
        if b == 0.0 {
            return Err(CalculatorError::InvalidInput("Division by zero"
                                  .to_string()));
        }
        Ok(a / b)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_add() {
        let calc = Calculator::new();
        assert_eq!(calc.add(2.0, 3.0), 5.0);
    }
    
    #[test]
    fn test_subtract() {
        let calc = Calculator::new();
        assert_eq!(calc.subtract(5.0, 3.0), 2.0);
    }
    
    #[test]
    fn test_safe_divide() {
        let calc = Calculator::new();
        assert_eq!(calc.safe_divide(6.0, 2.0).unwrap(), 3.0);
        assert!(calc.safe_divide(6.0, 0.0).is_err());
    }
}

Tests

Ruby (RSpec)

spec/spec_helper.rb

require "simple_calculator"

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations
       .include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

  config.shared_context_metadata_behavior = :apply_to_host_groups
  config.filter_run_when_matching :focus
  config.example_status_persistence_file_path = "spec/examples.txt"
  config.disable_monkey_patching!
  config.warnings = true

  if config.files_to_run.one?
    config.default_formatter = "doc"
  end

  config.order = :random
  Kernel.srand config.seed
end

spec/simple_calculator_spec.rb

require 'spec_helper'

RSpec.describe SimpleCalculator do
  it "has a version number" do
    expect(SimpleCalculator::VERSION).not_to be nil
  end

  describe ".add" do
    it "adds two numbers correctly" do
      expect(SimpleCalculator.add(2, 3)).to eq(5)
    end

    it "raises TypeError for non-numeric arguments" do
      expect { SimpleCalculator.add("2", 3) }
              .to raise_error(TypeError)
    end
  end

  describe ".subtract" do
    it "subtracts two numbers correctly" do
      expect(SimpleCalculator.subtract(5, 3)).to eq(2)
    end

    it "raises TypeError for non-numeric arguments" do
      expect { SimpleCalculator.subtract(5, "3") }
                 .to raise_error(TypeError)
    end
  end

  describe ".celsius_to_fahrenheit" do
    it "converts 0°C to 32°F" do
      expect(SimpleCalculator.celsius_to_fahrenheit(0)).to eq(32)
    end

    it "converts 100°C to 212°F" do
      expect(SimpleCalculator.celsius_to_fahrenheit(100)).to eq(212)
    end

    it "raises TypeError for non-numeric arguments" do
      expect { SimpleCalculator.celsius_to_fahrenheit("zero") }
              .to raise_error(TypeError)
    end
  end
end

Rust (Tests)

tests/integration_tests.rs

use simple_calculator::{add, subtract, celsius_to_fahrenheit, Calculator};

#[test]
fn test_crate_level_functions() {
    assert_eq!(add(2.0, 3.0), 5.0);
    assert_eq!(subtract(5.0, 3.0), 2.0);
    assert_eq!(celsius_to_fahrenheit(0.0), 32.0);
}

#[test]
fn test_calculator_safe_divide() {
    let calc = Calculator::new();
    let result = calc.safe_divide(10.0, 2.0);
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), 5.0);
    
    let error_result = calc.safe_divide(10.0, 0.0);
    assert!(error_result.is_err());
}

Configuration des projets

Ruby (Gem)

Gemfile

source "https://rubygems.org"

gemspec

group :development, :test do
  gem "rspec", "~> 3.10"
  gem "yard", "~> 0.9.27"
  gem "redcarpet", "~> 3.5" 
  # Pour le rendu Markdown dans YARD
  gem "rake", "~> 13.0"
end

Rakefile

require "bundler/gem_tasks"
require "rspec/core/rake_task"
require "yard"

RSpec::Core::RakeTask.new(:spec)

YARD::Rake::YardocTask.new do |t|
  t.files = ["lib/**/*.rb"]
  t.options = ["--markup", "markdown"]
  t.stats_options = ["--list-undoc"]
end

task :default => [:spec, :yard]

simple_calculator.gemspec

lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "simple_calculator"

Gem::Specification.new do |spec|
  spec.name          = "simple_calculator"
  spec.version       = SimpleCalculator::VERSION
  spec.authors       = ["Example Author"]
  spec.email         = ["author@example.com"]
  spec.summary       = "A simple calculator gem"
  spec.description   = "Performs basic calculations and conversions"
  spec.homepage      = "https://github.com/example/simple_calculator"
  spec.license       = "MIT"
  spec.files         = Dir["lib/**/*", "README.md"]
  spec.require_paths = ["lib"]
  
  spec.add_development_dependency "bundler", "~> 2.0"
  spec.add_development_dependency "rake", "~> 13.0"
  spec.add_development_dependency "rspec", "~> 3.10"
  spec.add_development_dependency "yard", "~> 0.9.27"
end

.yardopts

--markup markdown
--markup-provider redcarpet
--readme README.md
--title "SimpleCalculator Documentation"
--protected
--private
--embed-mixins
--output-dir doc/yard

Rust (Crate)

Cargo.toml

[package]
name = "simple_calculator"
version = "0.1.0"
edition = "2021"
authors = ["Example Author <author@example.com>"]
description = "A simple calculator library"
license = "MIT"
repository = "https://github.com/example/simple_calculator"
documentation = "https://docs.rs/simple_calculator"
readme = "README.md"

[dependencies]
thiserror = "1.0"

[dev-dependencies]
criterion = "0.3"

[lib]
name = "simple_calculator"
path = "src/lib.rs"

Comparaison des outils de documentation

Ruby (YARD)

YARD est un outil de documentation pour Ruby qui génère une documentation HTML à partir des commentaires dans le code.

Installation et configuration

# Installation
gem install yard

# Génération de la documentation
yard doc
# ou
rake yard

Exemple de commentaire YARD

# Converts Celsius to Fahrenheit
#
# @param celsius [Numeric] Temperature in Celsius
# @return [Numeric] Temperature in Fahrenheit
# @example
#   converter = Converter.new
#   converter.celsius_to_fahrenheit(0)  # => 32
# @raise [TypeError] If argument is not numeric
def celsius_to_fahrenheit(celsius)
  # implementation
end

Rust (Rustdoc)

Rustdoc est intégré à Rust et génère automatiquement la documentation à partir des commentaires de documentation (doc comments).

Installation et configuration

# Aucune installation nécessaire, rustdoc est inclus avec Rust
# Génération de la documentation
cargo doc --no-deps --open
# Options courantes
cargo doc --document-private-items # Inclure les éléments privés
cargo doc --no-deps # Ne pas inclure les dépendances

Exemple de commentaire Rustdoc

/// Converts a temperature from Celsius to Fahrenheit
///
/// # Examples
///
/// ```
/// use simple_calculator::Converter;
/// let converter = Converter::new();
/// assert_eq!(converter.celsius_to_fahrenheit(0.0), 32.0);
/// ```
pub fn celsius_to_fahrenheit(&self, celsius: f64) -> f64 {
    // implementation
}

Comparaison des systèmes de build et de tâches

Ruby (Rake)

Rake est un outil de build pour Ruby, similaire à Make, qui permet de définir des tâches.

Installation et configuration

# Installation
gem install rake

# Création d'un Rakefile
touch Rakefile

Exemple de Rakefile

require "bundler/gem_tasks"
require "rspec/core/rake_task"
require "yard"

# Définition des tâches RSpec
RSpec::Core::RakeTask.new(:spec)

# Définition des tâches YARD
YARD::Rake::YardocTask.new do |t|
  t.files = ["lib/**/*.rb"]
  t.options = ["--markup", "markdown"]
  t.stats_options = ["--list-undoc"]
end

# Tâche personnalisée
desc "Exécute les tests et vérifie la couverture de documentation"
task :quality => [:spec, :yard]

# Tâche par défaut
task :default => :quality

Exécution des tâches

# Exécuter la tâche par défaut
rake

# Exécuter une tâche spécifique
rake spec
rake yard
rake quality

# Lister toutes les tâches disponibles
rake -T

Rust (Cargo)

Cargo est le gestionnaire de paquets et système de build de Rust, intégré au langage.

Installation et configuration

# Aucune installation nécessaire, 
# Cargo est inclus avec Rust

# Création d'un nouveau projet
cargo new simple_calculator --lib

Exemple de commandes Cargo

# Compiler le projet
cargo build

# Exécuter les tests
cargo test

# Générer la documentation
cargo doc

# Vérifier le code sans compiler
cargo check

# Publier sur crates.io
cargo publish

Personnalisation avec Cargo Make

Pour des tâches plus complexes, on peut utiliser Cargo Make, un outil tiers :

# Installation
cargo install cargo-make

# Création d'un 
# fichier Makefile.toml
touch Makefile.toml

Exemple de Makefile.toml

[tasks.format]
command = "cargo"
args = ["fmt", "--all"]

[tasks.lint]
command = "cargo"
args = ["clippy", "--all-targets", "--all-features"]

[tasks.test]
command = "cargo"
args = ["test"]

[tasks.doc]
command = "cargo"
args = ["doc", "--no-deps", "--open"]

[tasks.ci]
dependencies = [
    "format",
    "lint",
    "test",
    "doc"
]

[tasks.default]
dependencies = ["ci"]

Exécution des tâches

# Exécuter la tâche par défaut
cargo make

# Exécuter une tâche spécifique
cargo make format
cargo make test
cargo make ci

Tableau comparatif

FonctionnalitéRubyRust
Système de buildRakeCargo
DocumentationYARDRustdoc
TestsRSpecTests intégrés + Cargo test
Gestion des dépendancesBundlerCargo
PublicationRubyGemscrates.io
FormatageRubocoprustfmt
Analyse statiqueRubocopClippy
Exécution des tâchesrake taskcargo command
PersonnalisationRakefileCargo Make (tiers)

Comparaison détaillée des systèmes de documentation

AspectYARD (Ruby)Rustdoc (Rust)
IntégrationExterne, via gemIntégré au langage
SyntaxeTags (@param, @return, etc.)Markdown avec sections (#Examples, etc.)
Tests dans la docNon exécutablesExécutés comme tests (cargo test --doc)
Générationyard doc ou rake yardcargo doc
HébergementRubydoc.info (manuel)docs.rs (automatique)
ThèmePersonnalisableStandard, peu personnalisable
RechercheBasiqueAvancée, avec index
Liens vers le code sourceOuiOui
GraphiquesDiagrammes de classesNon
StatistiquesCouverture de documentationNon

Exemple d'utilisation

Ruby

Installation de la gem

gem install simple_calculator

Utilisation

require 'simple_calculator'

# Utilisation des fonctions de module
puts SimpleCalculator.add(2, 3)                 # => 5
puts SimpleCalculator.subtract(5, 3)            # => 2
puts SimpleCalculator.celsius_to_fahrenheit(0)  # => 32

# Utilisation directe des classes
calculator = SimpleCalculator::Calculator.new
puts calculator.add(2, 3)                       # => 5

converter = SimpleCalculator::Converter.new
puts converter.celsius_to_fahrenheit(100)       # => 212

Rust

Installation du crate

cargo add simple_calculator

Utilisation

use simple_calculator::{add, subtract, celsius_to_fahrenheit, Calculator, Converter};

fn main() {
    // Utilisation des fonctions de module
    println!("{}", add(2.0, 3.0));                  // => 5
    println!("{}", subtract(5.0, 3.0));             // => 2
    println!("{}", celsius_to_fahrenheit(0.0));     // => 32

    // Utilisation directe des structures
    let calculator = Calculator::new();
    println!("{}", calculator.add(2.0, 3.0));       // => 5
    
    // Gestion d'erreurs avec Result
    match calculator.safe_divide(10.0, 2.0) {
        Ok(result) => println!("10 / 2 = {}", result),
        Err(e) => println!("Erreur: {}", e),
    }
    
    let converter = Converter::new();
    println!("{}", converter.celsius_to_fahrenheit(100.0)); // => 212
}

Workflow de développement

Ruby

Publication

# Mettre à jour la version dans lib/simple_calculator/version.rb
rake release

Documentation

bundle exec yard
open doc/yard/index.html

Tests

bundle exec rspec

Développement

# Éditer les fichiers dans lib/
vim lib/simple_calculator.rb

Création du projet

bundle gem simple_calculator

Rust

Publication

# Mettre à jour la version dans Cargo.toml
cargo publish

Documentation

cargo doc --open

Tests

cargo test

Développement

# Éditer les fichiers dans src/
vim src/lib.rs

Création du projet

cargo new simple_calculator --lib

Ecosystèmes & communautés

Similitudes dans la communauté

& gouvernance

Similitudes dans les domaines d'application

Similitudes dans l'apprentissage et adoption
 

Similitudes dans l'écosystème

Conclusion

Mots clés

Romain GEORGES

Open Source evangelist & Ruby enthousiast