point free procedure composition - ghostscript

Suppose I have two procedures p1 and p2 on the stack and I want to consume them and leave on the stack a new procedure that combines their effects. I would like a procedure to do this. This is easy enough if I am always willing to do a little dictionary bookkeeping. But can I do it without introducing any names? (Note that I want the resulting procedure, not just to execute the combined effects on the current stack.)
Consider for example
/compose {<< /f1 4 2 roll /f2 exch >>begin {f1 f2} end}bind def
This won't work of course because f1 and f2 will be unknown after end. But this broken code should illustrate what I'm after.

It's totally possible, and not terribly difficult. You make a new array with each procedure object followed by the executable name exec. Then make that array executable.
/combine { % {a} {b} . {{a} exec {b} exec}
/exec cvx exch % {a} exec {b}
/exec cvx % {a} exec {b} exec
4 array astore % [{a} exec {b} exec]
cvx % {{a} exec {b} exec}
} def
For a style closer to your original, with named arguments, I would write it like this:
% fun1 fun2 compose proc
/compose { 2 dict begin % f1 f2
{f2 f1}{exch def} forall %
({ //f1 exec //f2 exec }) % ({ //f1 exec //f2 exec })
cvx exec % { <f1> exec <f2> exec }
end } def
The //immediate-name syntax is very powerful. Here I use a code template in a string. When the string is executed cvx exec it invokes the scanner upon the contents and it is then that it automatically loads all tokens prefixed with double-slash //. The comment <f1> indicates the contents of the named variable. Just like an {executable array} in the program stream is not executed but yields the proc on the stack, execing a string containing one will also yield the proc on the stack.
For the named arguments style, I make use of a few special rules of postscript: executable arrays are not executed, thus the array of variable names can be written as an executable array and then used as data without any additional hassle. But by using the executable syntax, the contents -- the names -- can be written without the /s. So, instead of [ /f2 /f1 ] we can write the shorter { f2 f1 }.
The arguments part could also be factored into its own function.
/argsbegin { % a r g s _ {n a m e s} . -
dup length dict begin
{exch def} forall % currentdict:<</n _ /a s /m g /e r /s a>>
} def
/compose { {f2 f1} argsbegin
({//f1 exec //f2 exec}) token pop exch pop %another way to invoke the scanner
end } def
Or, to actually put the arguments the right way around, it could be like the following. It's just a little more awkward to simulate a backwards forall with a for loop.
/argsbegin { % a r g s _ {n a m e s} . -
dup length dup dict begin % a r g s _ {} n
1 sub -1 0 { % a r g s _ {} i
3 2 roll % a r g s {} i _
3 copy % a r g s {} i _ {} i _
pop % a r g s {} i _ {} i
get % a r g s {} i _ /s
exch def % a r g s {} i
pop % a r g s {}
} for % {}
pop
} def
/compose { {f1 f2} argsbegin
({//f1 exec //f2 exec}) cvx exec
end } def

Related

Tcl upvar and uplevel in performance

Let's say I have a variable which is one level up, which I just want to query its' value. I have two options:
uplevel { set var_name }
Or:
upvar var_name
If I need to query the variable just once, and not change it, which one should be faster?
You'll find that upvar is probably faster for this. Not necessarily, but most likely. (If you're worried about performance, time the alternatives.)
Note that they will both necessarily have to resolve the variable name; that's a cost that's going to be borne anyway. But the version with upvar doesn't involve moving code between contexts, so it is likely to be faster.
FWIW, when I try with the example below, my intuition is correct. (The key is that one uses the upvar bytecode opcode; the other does invokeStk, which is slower because that's the general command dispatcher and has a bunch of overhead necessary for other purposes.)
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
17.8188412 microseconds per iteration
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
25.4614022 microseconds per iteration
I prefer timerate for this kind of micro-benchmarking:
% namespace import ::tcl::unsupported::timerate
% timerate -calibrate {}
0.03257451263357219 µs/#-overhead 0.032807 µs/# 59499506 # 30481304 #/sec
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% timerate {foo 2} 10000
0.437240 µs/# 21285016 # 2287075 #/sec 9306.651 net-ms
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% timerate {foo 2} 10000
0.612693 µs/# 15497439 # 1632137 #/sec 9495.179 net-ms
(Answer holds, clearly: Use upvar).

Sort a String list by String length

I want to sort a list of String first by the length of the strings, and if the length is the same then it should sort lexically. I thought I could use the Data.List library and write my own compare function that does that. So the compare function should take a list of String as the argument and compare all the the elements (which are Strings). A compare function for Strings would look like this
comp a b
| length a > length b = GT
| length a < length b = LT
How could I address all the list elements with such a function?
First of all, your cmp function does not handle the case where the lengths are equal: you need to add that. Otherwise you'll get an runtime pattern match error:
comp a b
| length a > length b = GT
| length a < length b = LT
| otherwise = undefined -- TODO
also, note that this implementation sometimes computes the length twice, but it's likely that GHC optimizes this one away on its own, and we'll get to solving this later on more fundamentally anyway.
Then, once you've fixed your comp, all you need to do is pass it to Data.List.sortBy together with the list of strings you want to sort. An ipmplementation like that is provided below (<$> is the operator alias of fmap which works the same as map does on lists).
However, there's a better solution where you first compute the length of all elements in the list, by mapping each of the elements into a pair where the first member is the original string and the second one is its length. You then use a modified comp function that takes 2 pairs instead of just 2 strings, but otherwise behaves the same as your original comp. However, you then need to map the intermediate list back to just containing the strings (which is what the fst <$> is for, which is equivalent to map fst but, again, uses the, IMO nicer looking, <$> opetator).
So the somewhat naive solution would be:
sortByLenOrLex :: [String] -> [String]
sortByLenOrLex as = sortBy cmp as where
cmp a b | n > m = GT
| n < m = LT
| otherwise = compare a b
where n = length a
m = length b
and the more efficient one, as leftaroundabout points out, would be:
sortByLenOrLex' :: [String] -> [String]
sortByLenOrLex' as = fst <$> sortBy cmp (addLen <$> as) where
cmp (a,n) (b,m) | n > m = GT
| n < m = LT
| otherwise = compare a b
addLen x = (x, length x)
where the list is first amended with the lengths of each of its elements, so as to avoid duplicate, expensive length calls.
EDIT: please see chi's answer for a much nicer implementation of this algorithm!
Furthermore:
You can make your functions generic by making them operate on lists of lists of Ord:
sortByLenOrLex'' :: Ord a => [[a]] -> [[a]]
sortByLenOrLex'' as = fst <$> sortBy cmp (addLen <$> as) where
cmp (a,n) (b,m) | n > m = GT
| n < m = LT
| otherwise = compare a b
addLen x = (x, length x)
this gives you:
*Main> sortByLenOrLex'' [[1,2], [1,3], [1,2,3]]
[[1,2],[1,3],[1,2,3]]
...and if you want to make it as generic as possible, you can sort lists of Foldable of Ord:
sortByLenOrLex''' :: (Foldable f, Ord a) => [f a] -> [f a]
sortByLenOrLex''' as = unamend <$> sortBy cmp (amend <$> as) where
cmp (a,n,a') (b,m,b') | n > m = GT
| n < m = LT
| otherwise = compare a' b'
amend x = (x, length x, toList x)
unamend (x,_,_) = x
this gives you:
*Main> sortByLenOrLex''' [Just 3, Just 4, Just 3, Nothing]
[Nothing,Just 3,Just 3,Just 4]
*Main> sortByLenOrLex''' [(4,1),(1,1),(1,2),(1,1),(3,1)]
[(4,1),(1,1),(1,1),(3,1),(1,2)]
*Main> sortByLenOrLex''' [Left "bla", Right "foo", Right "foo", Right "baz"]
[Left "bla",Right "baz",Right "foo",Right "foo"]
*Main> sortByLenOrLex''' [(3,"hello"),(2,"goodbye"),(1,"hello")]
[(2,"goodbye"),(3,"hello"),(1,"hello")]
A variant of #Erik's solution, using some combinators from the library:
import Data.List
import Control.Arrow
sortByLen = map snd . sort . map (length &&& id)
This is essentially a Schwartzian transform.

Shell script to parse multiple rows from a single column

I am working through a really complex and long multi-conditional statement to do this and was wondering if anyone knew of a simpler method. I have a multi-column/multi-row list that I am trying to parse. What I need to do is take the first row which has the "*" in the 5th position and copy all those entries into the blank spaces on the next few rows and then discard the original top row. What complicates this a bit is that sometimes the next few rows may not have an empty space in all the other fields (see bottom half of original list). If that's the case, I want to take extra entry (Q1 below) and put it at the end of row, in a new column.
Original list:
A B C D ***** F G
E1
E2
E3
Q R S T ***** V W
U1
Q1 U2
Final output:
A B C D E1 F G
A B C D E2 F G
A B C D E3 F G
Q R S T U1 V W
Q R S T U2 V W Q1
Thanks in advance for help!
The concise/cryptic one liner:
awk '/[*]/{f=$0;p="[*]+";next}{r=$2?$2:$1;sub(p,r,f);p=r;print $2?f" "$1:f}' file
A B C D E1 F G
A B C D E2 F G
A B C D E3 F G
Q R S T U1 V W
Q R S T U2 V W Q1
Explanation:
/[*]+/ { # If line matches line with pattern to replace
line = $0 # Store line
pat="[*]+" # Store pattern
next # Skip to next line
}
{
if (NF==2) # If the current line has 2 fields
replace = $2 # We want to replace with the second
else # Else
replace = $1 # We want to replace with first first
sub(pat,replace,line) # Do the substitution
pat=replace # Next time the pattern to replace will have changed
if (NF==2) # If the current line has 2 fields
print line,$1 # Print the line with the replacement and the 1st field
else # Else
print line # Just print the line with the replacement
}
To run the script save it to a file such as script.awk and run awk -f script.awk file.

Change output of pause command in batch script

I'm writing a Windows batch script. By default, the pause command will pause the script and display the text "Press any key to continue...".
How do I modify this text to display my own text to the user?
You could hide the text from the pause command by using this:
pause >nul
Then you could echo your own message to tell the user it has paused:
echo The batch file has paused
So the full script might look like this:
#echo off
echo Hello World!
echo The batch file has paused
pause >nul
Here's a one-liner
pause>nul|set/p =any key to exit ...
It's slightly shorter (one less 'nul')
than Aacini's solution:
set/p<nul =any key to exit ...&pause>nul
and, with the 'pause' first, I think that
it's a little clearer what the intent is.
With both
cursor stays on the same line
ANY key works, not just 'enter'
Neither are as good, however, as the hypothetical
pause/t any key to exit ...
It's hard to believe that 'pause' has survived
35 years without this ability ;-)
The solutions with 'echo' have the possibly undesirable
trailing new-line,
but do provide for multiple lines of text:
Pause>nul|(echo All your bases &echo are belong to us &echo Press any key to die...)
bv
"Not really what I was looking for, I was wondering whether there was a way of actually changing the output text of the Pause command, not just a workaround to it." – Hashim
Yes, you can! But you must be aware that PAUSE is an internal command of CMD.EXE program, so, to modify the message that PAUSE show, you must modify CMD.EXE file. To do that, you must use an editor that may modify binary files. I used XVI32 program via these steps:
1- Copy CMD.EXE file to a new folder created for this purpose: COPY %COMSPEC%
2- Edit the copy of CMD.EXE with XVI32.EXE program:
2.1- Locate the message you want. Messages are stored in 16-bits elements with the high byte equal zero. To locate a message:
2.1.1- In Search> Find> Text string> enter the message you want.
2.1.2- Convert Text -> Hex
2.1.3- Insert a zero after each letter-value
2.1.4- Press Ok
2.2- Modify the message for the new one. Modify existent letters only and keep zeros in place. Note that you can NOT extend any message.
2.3- End the edition and save the modified file.
You may now run CMD.EXE to get the modified PAUSE message. I made a test of this procedure:
C:\DOCUME~1\Antonio\MYDOCU~1\My Webs\XVI32 Hex File Editor
>pause
Press any key to continue . . .
C:\DOCUME~1\Antonio\MYDOCU~1\My Webs\XVI32 Hex File Editor
>cmd
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\DOCUME~1\Antonio\MYDOCU~1\My Webs\XVI32 Hex File Editor
>pause
Oprime una tecla para seguir. .
Notes to everyone that read this answer:
NOTE 1: Please, don't post that comment saying that modifying CMD.EXE file must NEVER be done! I think the same. I just posted this answer so the OP realized what he really asked for...
NOTE 2: The reviewing of CMD.EXE file with a text editor, like Notepad, is very interesting. You may see all the internal commands, interesting details (like =ExitCode and =ExitCodeAscii variables), all the error messages, etc. For example, these are the internal commands:
C O L O R T I T L E C H D I R C L S C M D E X T V E R S I O N
D E F I N E D C O P Y P A T H P R O M P T P U S H D P O P D
A S S O C F T Y P E D A T E D E L D I R E C H O E N D L O C A L
E R A S E E R R O R L E V E L E X I T E X I S T B R E A K F O R
G O T O I F K E Y S M K D I R M D N O T P A U S E R D
R E M M O V E R E N A M E R E N R M D I R S E T S E T L O C A L
S H I F T S T A R T T I M E T Y P E V E R I F Y V E R V O L = , ; + / [ ] " : . \
P A T H E X T P A T H P R O M P T
F O R / ? I F / ? R E M / ?
% s % s
% s
/ A / P : E O F
f d p n x s a t z D O
/ L / D / F / R I N E L S E ( % s ) % s % s % s % s
% c % c % s % s & ( ) [ ] { } ^ = ; ! % ' + , ` ~
There is no way to change the text of the pause command. However you might want to look at the choice command. You can change the text it prints. The only downside is that you need to provide a list of acceptable characters.
Already many solutions. Another variation that makes some sense:
echo Hit any key to continue...&pause>nul
Another dirty solution would be something like this,
SET /P =Press enter to return to the menu . . .
GOTO :menu
The benefit of this is that the cursor stays on the same line as the message, just like with the PAUSE command.
The downside is that it only listens to the enter key.
Here’s another trick
Pause. >nul | echo. Press something to continue
Starting from Windows 2000 (so, not XP) you can use the choice command which is far more powerful than either pause or set /p.
Besides being able to specify your own prompt text, you can also require the user to type a specific key, and only that key, instead of being limited to, and requiring, [Enter] to be pressed.
Also, you can prompt the user to press a number of different keys and take action based on which key was pressed.
Type choice /? for help, or read more about it here: Wikipedia: choice (command)
You could do it like this!
#echo off
echo Hello World!
echo:
echo Press 1 to continue
set /p letter=
if %letter% == 1 goto a ;or instead of goto you could write start and the file or website you want to start
pause >nul
:a
cls
echo BYE NOW!
pause >nul
pause|echo text you want displayed
Since I dont see it suggested and every dog on the internet has had a go, but me.
This may not have worked under XP, as required by OP, but is valid for any newer system like my current Win7 :-)
Dirty version (no message) |keys ON does nothing, but block the press any key ...
timeout -1|Keys ON
can be used for message after
#timeout -1|Keys ON&echo I'm back
This one will pause and show a response until accepted then return to prompt/next cmd line
#timeout -1|Echo Hello Padawan %userprofile:~9%, Press a key, you can!
:on any keys
#echo Welcome to the dark side

ML Expression, help line by line

val y=2;
fun f(x) = x*y;
fun g(h) = let val y=5 in 3+h(y) end;
let val y=3 in g(f) end;
I'm looking for a line by line explanation. I'm new to ML and trying to decipher some online code. Also, a description of the "let/in" commands would be very helpful.
I'm more familiar with ocaml but it all looks the same to me.
val y=2;
fun f(x) = x*y;
The first two lines bind variables y and f. y to an integer 2 and f to a function which takes an integer x and multiplies it by what's bound to y, 2. So you can think of the function f takes some integer and multiplies it by 2. (f(x) = x*2)
fun g(h) = let val y=5
in
3+h(y)
end;
The next line defines a function g which takes some h (which turns out to be a function which takes an integer and returns an integer) and does the following:
Binds the integer 5 to a temporary variable y.
You can think of the let/in/end syntax as a way to declare a temporary variable which could be used in the expression following in. end just ends the expression. (this is in contrast to ocaml where end is omitted)
Returns the sum of 3 plus the function h applying the argument y, or 5.
At a high level, the function g takes some function, applies 5 to that function and adds 3 to the result. (g(h) = 3+h(5))
At this point, three variables are bound in the environment: y = 2, f = function and g = function.
let val y=3
in
g(f)
end;
Now 3 is bound to a temporary variable y and calls function g with the function f as the argument. You need to remember that when a function is defined, it keeps it's environment along with it so the temporary binding of y here has no affect on the functions g and f. Their behavior does not change.
g (g(h) = 3+h(5)), is called with argument f (f(x) = x*2). Performing the substitutions for parameter h, g becomes 3+((5)*2) which evaluates to 13.
I hope this is clear to you.

Resources