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
-
#caar ⇒ Object
In their basic form, they are only marginally useful.
- #cadr ⇒ Object
-
#car ⇒ Object
Everybody knows Lispy functions #car, #cdr.
- #cdar ⇒ Object
- #cddr ⇒ Object
-
#cdr ⇒ Object
d: all except first.
-
#method_missing(mτ_sym, *args, &block) ⇒ Object
These compositions can extend ad infinitum: caaar, caadr, cadar,…
- #respond_to_missing?(mτ_sym, include_private = false) ⇒ Boolean
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:
******************************************************************
-
Twin-barrel piping: Instead of just one pipeline, in which the
operations are applied in sequence, Pyper has 2 parallel pipelines.
-
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.
-
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')
-
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.
-
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
#caar ⇒ Object
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 |
#cadr ⇒ Object
17 |
# File 'lib/pyper.rb', line 17 def cadr; drop(1).first end |
#car ⇒ Object
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 |
#cdar ⇒ Object
16 |
# File 'lib/pyper.rb', line 16 def cdar; first.drop 1 end |
#cddr ⇒ Object
18 |
# File 'lib/pyper.rb', line 18 def cddr; drop(1).drop(1) end |
#cdr ⇒ Object
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
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 |