Skip to content

Commit 704ed9f

Browse files
committed
Merge pull request #37 from mohawkjohn/issue_33
Adds SymEngine::symbols() and allows Symbol.new to take a Ruby symbol
2 parents a968a45 + d913a15 commit 704ed9f

File tree

3 files changed

+98
-4
lines changed

3 files changed

+98
-4
lines changed

ext/symengine/ruby_symbol.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
#include "ruby_symbol.h"
22

3-
VALUE csymbol_init(VALUE self, VALUE name) {
4-
Check_Type(name, T_STRING);
5-
basic_struct *this;
6-
char *str_ptr = StringValueCStr(name);
3+
VALUE csymbol_init(VALUE self, VALUE name_or_id) {
4+
char *str_ptr;
5+
6+
switch (TYPE(name_or_id)) {
7+
case T_STRING:
8+
str_ptr = StringValueCStr(name_or_id);
9+
break;
10+
case T_SYMBOL:
11+
str_ptr = rb_id2name(rb_to_id(name_or_id));
12+
break;
13+
default:
14+
rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol or String)", rb_obj_classname(name_or_id));
15+
}
716

17+
basic_struct *this;
818
Data_Get_Struct(self, basic_struct, this);
919

1020
symbol_set(this, str_ptr);

lib/symengine.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1+
module SymEngine
2+
class << self
3+
4+
# Defines a shortcut for SymEngine::Symbol.new() allowing multiple symbols
5+
# to be created all at once.
6+
#
7+
# Examples:
8+
#
9+
# x, y = SymEngine.symbols(%i{x y})
10+
# x, y = SymEngine.symbols(%w{x y})
11+
# x, y = SymEngine.symbols([:x, :y])
12+
# x, y = SymEngine.symbols(['x', 'y'])
13+
# x, y = SymEngine.symbols('x', 'y')
14+
# x, y = SymEngine.symbols('x y')
15+
#
16+
def symbols ary_or_string, *params
17+
# Want to make sure we can accept an array or a bunch of splatted arguments
18+
if params.size > 0
19+
ary_or_string = (ary_or_string.is_a?(String) ? [ary_or_string] : ary_or_string).concat(params)
20+
elsif ary_or_string.is_a?(String)
21+
# or accept a string
22+
ary_or_string = ary_or_string.split
23+
end
24+
25+
# Make an Array of SymEngine::Symbols from the parameters we received,
26+
# now that they're normalized.
27+
ary_or_string.map do |symbol_or_string|
28+
SymEngine::Symbol.new(symbol_or_string)
29+
end
30+
end
31+
end
32+
end
33+
134
require 'symengine/symengine'
235
require 'symengine/iruby'
336
require 'symengine/basic'

spec/symbol_spec.rb

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,53 @@
11
require 'spec_helper'
22

3+
4+
35
describe SymEngine do
46
before :each do
57
end
68

9+
describe '.symbols' do
10+
before :all do
11+
12+
# Create a shortcut Proc to DRY up code.
13+
#
14+
# Call this with the number of symbols we expect to get out
15+
# and the argument we want to provide it.
16+
@test_symbols_method = Proc.new do |count_symbols, *args|
17+
symbols = SymEngine.symbols(*args)
18+
symbols.each do |symbol|
19+
expect(symbol).to be_an_instance_of SymEngine::Symbol
20+
end
21+
expect(symbols.size).to eql(count_symbols)
22+
end
23+
end
24+
25+
context 'with a white-space separated string as an argument' do
26+
it 'returns an Enumerable of Symbol objects' do
27+
@test_symbols_method.call(2, 'x y')
28+
end
29+
end
30+
31+
context 'with an array of Ruby Symbols as an argument' do
32+
it 'returns an Enumerable of Symbol objects' do
33+
# @test_symbols_method.call(2, %i{x y}) # Ruby 2.0 and higher only
34+
@test_symbols_method.call(2, [:x, :y])
35+
end
36+
end
37+
38+
context 'with an array of Ruby Strings as an argument' do
39+
it 'returns an Enumerable of Symbol objects' do
40+
@test_symbols_method.call(2, %w{x y})
41+
end
42+
end
43+
44+
context 'with a splatted argument' do
45+
it 'returns an Enumerable of Symbol objects' do
46+
@test_symbols_method.call(2, 'x', 'y')
47+
end
48+
end
49+
end
50+
751
describe SymEngine::Symbol do
852
before :each do
953
end
@@ -15,6 +59,13 @@
1559
expect(symbol).to be_an_instance_of SymEngine::Symbol
1660
end
1761
end
62+
63+
context 'with a Ruby symbol as an argument' do
64+
it 'returns a Symbol object' do
65+
symbol = SymEngine::Symbol.new(:x)
66+
expect(symbol).to be_an_instance_of SymEngine::Symbol
67+
end
68+
end
1869
end
1970
end
2071
end

0 commit comments

Comments
 (0)