Module: JSE::Functors::Utils

Defined in:
lib/jse/functors/utils.rb

Constant Summary collapse

UTILS_FUNCTORS =
{
  "$not"   => method(:not_fn),
  "$list?" => method(:listp),
  "$map?"  => method(:mapp),
  "$null?" => method(:nullp),
  "$get"   => method(:get_fn),
  "$set"   => method(:set_fn),
  "$del"   => method(:del_fn),
  "$conj"  => method(:conj),
  "$and"   => method(:and_fn),
  "$or"    => method(:or_fn),
}.freeze

Class Method Summary collapse

Class Method Details

.and_fn(env, *args) ⇒ Object



13
14
15
16
17
18
19
# File 'lib/jse/functors/utils.rb', line 13

def self.and_fn(env, *args)
  return true if args.empty?
  args.each do |arg|
    return false unless eval_arg(env, arg)
  end
  true
end

.conj(env, *args) ⇒ Object



91
92
93
94
95
96
97
# File 'lib/jse/functors/utils.rb', line 91

def self.conj(env, *args)
  raise "$conj requires exactly 2 arguments" unless args.length == 2
  elem = eval_arg(env, args[0])
  lst = eval_arg(env, args[1])
  raise "$conj second argument must be a list" unless lst.is_a?(Array)
  lst + [elem]
end

.del_fn(env, *args) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/jse/functors/utils.rb', line 76

def self.del_fn(env, *args)
  raise "$del requires (collection, key)" if args.length < 2
  coll = eval_arg(env, args[0])
  key = eval_arg(env, args[1])
  if coll.is_a?(Hash)
    coll.delete(key) { raise KeyError, "Key '#{key}' not found" }
  elsif coll.is_a?(Array)
    raise "$del on list requires integer index" unless key.is_a?(Integer)
    coll.delete_at(key)
  else
    raise "$del first argument must be map or list"
  end
  coll
end

.eq2(env, *args) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/jse/functors/utils.rb', line 99

def self.eq2(env, *args)
  evaluated = args.map { |a| eval_arg(env, a) }
  case evaluated.length
  when 1 then true
  when 2 then evaluated[0] == evaluated[1]
  else
    evaluated.each_cons(2).all? { |a, b| a == b }
  end
end

.eval_arg(env, arg) ⇒ Object



4
5
6
# File 'lib/jse/functors/utils.rb', line 4

def self.eval_arg(env, arg)
  arg.respond_to?(:apply) ? env.eval(arg) : arg
end

.get_fn(env, *args) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/jse/functors/utils.rb', line 45

def self.get_fn(env, *args)
  raise "$get requires (collection, key)" if args.length < 2
  coll = eval_arg(env, args[0])
  key = eval_arg(env, args[1])
  if coll.is_a?(Hash)
    coll[key]
  elsif coll.is_a?(Array)
    raise "$get on list requires integer index" unless key.is_a?(Integer)
    raise IndexError, "Index #{key} out of range" if key < 0 || key >= coll.length
    coll[key]
  else
    raise "$get first argument must be map or list"
  end
end

.listp(env, *args) ⇒ Object



30
31
32
33
# File 'lib/jse/functors/utils.rb', line 30

def self.listp(env, *args)
  return false if args.empty?
  eval_arg(env, args[0]).is_a?(Array)
end

.mapp(env, *args) ⇒ Object



35
36
37
38
# File 'lib/jse/functors/utils.rb', line 35

def self.mapp(env, *args)
  return false if args.empty?
  eval_arg(env, args[0]).is_a?(Hash)
end

.not_fn(env, *args) ⇒ Object



8
9
10
11
# File 'lib/jse/functors/utils.rb', line 8

def self.not_fn(env, *args)
  return true if args.empty?
  !eval_arg(env, args[0])
end

.nullp(env, *args) ⇒ Object



40
41
42
43
# File 'lib/jse/functors/utils.rb', line 40

def self.nullp(env, *args)
  return true if args.empty?
  eval_arg(env, args[0]).nil?
end

.or_fn(env, *args) ⇒ Object



21
22
23
24
25
26
27
28
# File 'lib/jse/functors/utils.rb', line 21

def self.or_fn(env, *args)
  return false if args.empty?
  args.each do |arg|
    val = eval_arg(env, arg)
    return val if val
  end
  false
end

.set_fn(env, *args) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/jse/functors/utils.rb', line 60

def self.set_fn(env, *args)
  raise "$set requires (collection, key, value)" if args.length < 3
  coll = eval_arg(env, args[0])
  key = eval_arg(env, args[1])
  val = eval_arg(env, args[2])
  if coll.is_a?(Hash)
    coll[key] = val
  elsif coll.is_a?(Array)
    raise "$set on list requires integer index" unless key.is_a?(Integer)
    coll[key] = val
  else
    raise "$set first argument must be map or list"
  end
  coll
end