Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions ext/symengine/ruby_symbol.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
#include "ruby_symbol.h"

VALUE csymbol_init(VALUE self, VALUE name) {
Check_Type(name, T_STRING);
basic_struct *this;
char *str_ptr = StringValueCStr(name);
VALUE csymbol_init(VALUE self, VALUE name_or_id) {
char *str_ptr;

switch (TYPE(name_or_id)) {
case T_STRING:
str_ptr = StringValueCStr(name_or_id);
break;
case T_SYMBOL:
str_ptr = rb_id2name(rb_to_id(name_or_id));
break;
default:
rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol or String)", rb_obj_classname(name_or_id));
}

basic_struct *this;
Data_Get_Struct(self, basic_struct, this);

symbol_set(this, str_ptr);
Expand Down
33 changes: 33 additions & 0 deletions lib/symengine.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
module SymEngine
class << self

# Defines a shortcut for SymEngine::Symbol.new() allowing multiple symbols
# to be created all at once.
#
# Examples:
#
# x, y = SymEngine.symbols(%i{x y})
# x, y = SymEngine.symbols(%w{x y})
# x, y = SymEngine.symbols([:x, :y])
# x, y = SymEngine.symbols(['x', 'y'])
# x, y = SymEngine.symbols('x', 'y')
# x, y = SymEngine.symbols('x y')
#
def symbols ary_or_string, *params
# Want to make sure we can accept an array or a bunch of splatted arguments
if params.size > 0
ary_or_string = (ary_or_string.is_a?(String) ? [ary_or_string] : ary_or_string).concat(params)
elsif ary_or_string.is_a?(String)
# or accept a string
ary_or_string = ary_or_string.split
end

# Make an Array of SymEngine::Symbols from the parameters we received,
# now that they're normalized.
ary_or_string.map do |symbol_or_string|
SymEngine::Symbol.new(symbol_or_string)
end
end
end
end

require 'symengine/symengine'
require 'symengine/iruby'
require 'symengine/basic'
51 changes: 51 additions & 0 deletions spec/symbol_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,53 @@
require 'spec_helper'



describe SymEngine do
before :each do
end

describe '.symbols' do
before :all do

# Create a shortcut Proc to DRY up code.
#
# Call this with the number of symbols we expect to get out
# and the argument we want to provide it.
@test_symbols_method = Proc.new do |count_symbols, *args|
symbols = SymEngine.symbols(*args)
symbols.each do |symbol|
expect(symbol).to be_an_instance_of SymEngine::Symbol
end
expect(symbols.size).to eql(count_symbols)
end
end

context 'with a white-space separated string as an argument' do
it 'returns an Enumerable of Symbol objects' do
@test_symbols_method.call(2, 'x y')
end
end

context 'with an array of Ruby Symbols as an argument' do
it 'returns an Enumerable of Symbol objects' do
# @test_symbols_method.call(2, %i{x y}) # Ruby 2.0 and higher only
@test_symbols_method.call(2, [:x, :y])
end
end

context 'with an array of Ruby Strings as an argument' do
it 'returns an Enumerable of Symbol objects' do
@test_symbols_method.call(2, %w{x y})
end
end

context 'with a splatted argument' do
it 'returns an Enumerable of Symbol objects' do
@test_symbols_method.call(2, 'x', 'y')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that you test the following:

    #    x, y = SymEngine.symbols(%i{x y})
    #    x, y = SymEngine.symbols(%w{x y})
    #    x, y = SymEngine.symbols('x', 'y')
    #    x, y = SymEngine.symbols('x y')

Based on your comment above, should we also test these:

    #    x, y = SymEngine.symbols([:x, :y])
    #    x, y = SymEngine.symbols(['x', 'y'])

I can see that you test SymEngine::Symbol.new('x') and SymEngine::Symbol.new(:x) below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%i{x y} is the same as [:x, :y], and %w{x y} is the same as ['x', 'y'].

I suppose we could also be exhaustive and test SymEngine.symbols(:x, :y), but it follows the same execution path as SymEngine.symbols('x', 'y'), so I think it's redundant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. Then all is good.

end
end
end

describe SymEngine::Symbol do
before :each do
end
Expand All @@ -15,6 +59,13 @@
expect(symbol).to be_an_instance_of SymEngine::Symbol
end
end

context 'with a Ruby symbol as an argument' do
it 'returns a Symbol object' do
symbol = SymEngine::Symbol.new(:x)
expect(symbol).to be_an_instance_of SymEngine::Symbol
end
end
end
end
end