Atom_lang

I remember Euphoria.. the programming language.
This is not that.. but the inspiration came from there.

# frozen_string_literal: true

require './atom'
require './lang'

l = Lang.new

l << [3, 8, 11, 21, 9]

until l.empty? do p l>1 end
# 3
# 8
# 11
# 21
# 9

l >> [1,2,3] << [4,5,6] # [1, 2, 3, 4, 5, 6]

res = l & ->{ it.even? } | ->{ Atom.new(it * 2) }
p res # => [(4/1), (8/1), (12/1)]

p res | -> { (it * Math::PI).rat(2) } # => [(88/7), (201/8), (377/10)]

this is atom Link to heading


class Atom < Numeric
  include Comparable
  attr_reader :val

  def initialize(val) = (@val = val.to_r)

  def <=>(o) = (@val <=> (o.is_a?(Atom) ? o.val : o))
  def coerce(o) = [Atom.new(o), self]

  [:+, :-, :*, :/, :%, :**].each {|op|
    define_method(op) { |o| Atom.new(@val.send(op, (o.is_a?(Atom) ? o.val : o))) }
  }
  
  [:to_f, :to_i, :to_r].each {|op| define_method(op) { @val.send(op) } }

  # rationalize to n decimal places (dp)
  # (see (3.14/2).rationalize(0.001) # for reference)
  def rationalize(dp) = Atom.new(@val.rationalize(10**-dp))
  alias_method :rat, :rationalize

  def to_s = ( @val.to_f.to_s )

end

this is lang Link to heading

class Lang
  attr_reader :ar

  def initialize = ( @ar = [] )

  def <<(obj) = ( self.tap { @ar.push(*Array(obj)) } )
  def >>(obj) = ( self.tap { @ar.unshift(*Array(obj)) } )
  def <(n=1) = ( n == 1 ? @ar.pop : @ar.pop(n) )
  def >(n=1) = ( n == 1 ? @ar.shift : @ar.shift(n) )
  def |(fn) = Lang.new.tap { it << @ar.map(&fn) }
  def &(fn) = Lang.new.tap { it << @ar.filter(&fn) }

  def inspect = ( @ar.map(&:to_r) )
  def empty? = @ar.empty?
end