Module: Pyper

Defined in:
lib/pyper.rb,
lib/pyper/version.rb

Overview

Pyper is an extension of the Lispy car/cdr idea.

Defined Under Namespace

Classes: PostfixMachine

Constant Summary collapse

VERSION =
"1.0.1"
DEBUG =
false

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(mτ_sym, *args, &block) ⇒ Object

These compositions can extend ad infinitum: caaar, caadr, cadar,… caaaar, caaadr, … caaaaar, …, cadaadr, … …

The combination of ‘a’ and ‘d’ letter controls, in reverse order, the combination in which car and cdr is applied in a single pipeline.

Pyper adds a few modifications and extensions to this idea:

******************************************************************

  1. Twin-barrel piping: Instead of just one pipeline, in which the

operations are applied in sequence, Pyper has 2 parallel pipelines.

  1. Greek letters τ, π, χ as method delimiters: Instead of ‘c’ and ‘r’ of

car/cdr family, Pyper methods start and end with any of the characters ‘τ’, ‘π’, ‘χ’ (small Greek tau, pi and chi). Choice of the character conveys specific meaning, which is best explained by case enumeration:

τ…τ means single-pipe input and output, τ…π means single-pipe input, double-pipe output τ…χ means single-pipe input, double-pipe output with a swap π…τ means double-pipe input, single-pipe output . . . χ…χ means double-pipe input with a swap, and same for the output

(Mnemonic for this is, that τ has one (vertical) pipe, π has two pipes, and χ looks like two pipes crossed)

As for the meaning, single-pipe input means, that a single object (the message receiver) is fed to the pipeline. Double-pipe input means, that the receiver is assumed to respond to methods #size and #[], its size is 2, and this being fulfilled, pipeline 0 and 1 are initialized respectively with the first and second element of the receiver as per method #[]. Double-pipe input with swap is the same, but the two elements of the receiver are swapped: pipeline 1 receives the first, pipeline 0 the second.

  1. Postfix order of commands: While traditional car/cdr family of

methods applies the letters in the prefix order (from right to left), Pyper uses postfix order (left to right).

Example: #cdar becomes τadτ (‘da’ reversed to ‘ad’)

#cadaar becomes τaadaτ ('adaa' reversed to 'aada')
  1. Extended set of commands: The set of command characters, which in the

traditional car/cdr method family consists only of two characters, ‘a’ and ‘d’, is greatly extended.

For example, apart from ‘a’, mening first, ‘b’ means second, and ‘c’ means third:

[“See”, “you”, “later”, “alligator”].τaτ #=> “See” [“See”, “you”, “later”, “alligator”].τbτ #=> “you” [“See”, “you”, “later”, “alligator”].τcτ #=> “later”

For another example, apart from ‘d’, meaning all except first, ‘e’ means all except first two, and ‘f’ means all except first three:

“See”, “you”, “later”, “alligator”].τdτ = [“you”, “later”, “alligator”
“See”, “you”, “later”, “alligator”].τeτ = [“later”, “alligator”
“See”, “you”, “later”, “alligator”].τfτ = [“alligator”

These command characters can be combined just like ‘a’ and ‘d’ letters in the traditional car/cdr family - just beware of the Pyper’s postfix order:

“See”, “you”, “later”, “alligator”].τddτ = [“later”, “alligator”
“See”, “you”, “later”, “alligator”].τdeτ = [“alligator”

[“See”, “you”, “later”, “alligator”].τdeaτ = “alligator” [“See”, “you”, “later”, “alligator”].τdeadτ = “lligator” [“See”, “you”, “later”, “alligator”].τdeafτ = “igator” [“See”, “you”, “later”, “alligator”].τdeafbτ = “g”

Many more command characters are available.

  1. Method arguments are possible: Unlike the traditional car/cdr family,

Pyper methods accept arguments. Regardless of the combination of the command characters, any Pyper method can accept an arbitrary number of arguments, which are [collected] into the ‘args’ variable, from which the methods triggered by the command characters may take their arguments as their arity requires.

******************************************************************

So much for the main concepts. As for the character meanings, those are defined as PostfixMachine methods of the same name (the name consists of 1 or 2 characters). At the moment, it is necessary to read the PostfixMachine code as their documentation.



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/pyper.rb', line 112

def method_missing( mτ_sym, *args, &block )
  pyperλ = lambda { | opts |
    mτ_string = PostfixMachine.new( $1 ).write_mτ( mτ_sym, opts )
    mτ_string.gsub! /^alpha = alpha\n/, "alpha\n"    # workaround
    mτ_string.gsub! /^alpha\nalpha\n/, "alpha\n"     # workaround
    mτ_string.gsub! /^alpha\nalpha =/, "alpha ="     # workaround
    mτ_string.gsub! /^alpha = alpha =/, 'alpha ='    # workaround
    puts mτ_string if Pyper::DEBUG
    self.class.module_eval( mτ_string )
    send( mτ_sym, *args, &block )
  }
  puts "received msg #{mτ_sym}" if Pyper::DEBUG
  case mτ_sym.to_s
  when /^τ(.+)τ$/ then pyperλ.( op: 1, ret: 1 )
  when /^π(.+)τ$/ then pyperλ.( op: 2, ret: 1 )
  when /^χ(.+)τ$/ then pyperλ.( op: -2, ret: 1 )
  when /^τ(.+)π$/ then pyperλ.( op: 1, ret: 2 )
  when /^π(.+)π$/ then pyperλ.( op: 2, ret: 2 )
  when /^χ(.+)π$/ then pyperλ.( op: -2, ret: 2 )
  when /^τ(.+)χ$/ then pyperλ.( op: 1, ret: -2 )
  when /^π(.+)χ$/ then pyperλ.( op: 2, ret: -2 )
  when /^χ(.+)χ$/ then pyperλ.( op: -2, ret: -2 )
  else super end
end

Instance Method Details

#caarObject

In their basic form, they are only marginally useful. Their popularity stems from their compositions:



15
# File 'lib/pyper.rb', line 15

def caar; first.first end

#cadrObject



17
# File 'lib/pyper.rb', line 17

def cadr; drop(1).first end

#carObject

Everybody knows Lispy functions #car, #cdr. In Ruby, these functions can be defined for example as:



10
# File 'lib/pyper.rb', line 10

def car; first end

#cdarObject



16
# File 'lib/pyper.rb', line 16

def cdar; first.drop 1 end

#cddrObject



18
# File 'lib/pyper.rb', line 18

def cddr; drop(1).drop(1) end

#cdrObject

d: all except first



11
# File 'lib/pyper.rb', line 11

def cdr; drop 1 end

#respond_to_missing?(mτ_sym, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


137
138
139
140
141
142
143
# File 'lib/pyper.rb', line 137

def respond_to_missing?( mτ_sym, include_private = false )
  case mτ_sym.to_s
  when /^τ(\w+)τ$/, /^π(\w+)τ$/, /^χ(\w+)τ$/,
    /^τ(\w+)π$/, /^π(\w+)π$/, /^χ(\w+)π$/,
    /^τ(\w+)χ$/, /^π(\w+)χ$/, /^χ(\w+)χ$/ then true
  else super end
end