## Generalised composition [scheme]
(define (compose . fns)
(define (make-chain fn chain)
(lambda args
(call-with-values (lambda () (apply fn args)) chain)))
(fold make-chain values fns))
Most people have worked with a simple kind of function composition: one that is essentially (lambda (f g) (lambda (x) (f (g x)))). SRFI 41 (http://srfi.schemers.org/srfi-41/srfi-41.html) describes a more general composition, that takes an arbitrary number of functions, and that allows each function to return multiple values. Here's my version of the same idea, but using "fold" from SRFI 1 (http://srfi.schemers.org/srfi-1/srfi-1.html), which I think is much cleaner from a functional programming point of view. Feel free to refactor this to make it even more functional. :-)
2009-04-22T04:24:55+00:00
836
Lisp
generalised-compose
1
Generalised composition
2009-04-22T05:07:18+00:00
611
611
http://chris.jester-young.name/
Chris Jester-Young
4.3333
29
(define (remove-subnodes n L)
(cond ((null? L) `())
((= n (car L)) L)
(else (remove-subnodes n (cdr L)))))
(define (subnode-of? n1 n2)
(< n1 n2))
(define (equal-nodes? n1 n2)
(= n1 n2))
; Take a list of numbers and build a list
; where subnodes are 1 less than thier parent
; nodes on the same level are equal.
;
; (build-list `(0 1 1 2 2 1 1 2 1 0)
; => (0 (1 1 (2 2) 1 1 (2) 1) 0)
;
; (build-list `(0 1 2 3 4 5 1 0))
; => (0 (1 (2 (3 (4 (5)))) 1) 0)
;
; (build-list `(1 2 1 2))
; => (1 (2) 1 (2))
;
(define (build-list L)
(define (helper n L)
(cond ((null? L) `())
((subnode-of? n (car L))
(cons (cons (car L)
(helper (car L) (cdr L)))
(helper n (remove-subnoes n (cdr L)))))
((equal-nodes? n (car L))
(cons (car L)
(helper (car L) (cdr L))))
(else `())))
(cons (car L) (helper (car L) (cdr L))))
This is written in a dialect of lisp: scheme. The first 3 functions are helper functions, the main function is the last function. Basically it creates a list of varying depths by parsing a list of numbers. Each number represents the depth that the element in the new list should have. I'm hoping someone can come up with a more straight forward way to accomplish what the below code does.
2008-09-09T05:35:15+00:00
486
Lisp
super-simple-parser-in-scheme
0
Super Simple Parser in Scheme
2008-09-09T15:53:24+00:00
1000
1000
http://rooster.myopenid.com
rooster.myopenid.com
0.0
0
## Main program [scheme]
#!/usr/bin/guile \
-e main -s
!#
(use-modules
(srfi srfi-1)
(srfi srfi-4)
(ice-9 getopt-long))
(define (u8+ . args)
(logand (apply + args) 255))
(define (make-sbox key rounds)
(let
((sbox (apply u8vector (iota 256)))
(s2 (apply vector (take (apply circular-list
(map char->integer (string->list key))) 256)))
(j 0))
(do
((k rounds (- k 1)))
((< k 1))
(for-each
(lambda (i)
(let
((temp (u8vector-ref sbox i)))
(set! j (u8+ j temp (vector-ref s2 i)))
(u8vector-set! sbox i (u8vector-ref sbox j))
(u8vector-set! sbox j temp)))
(iota 256)))
(vector-fill! s2 0)
sbox))
(define (crypt-loop sbox)
(let loop
((i 1)
(j 0))
(let
((ch (read-char)))
(if (not (eof-object? ch))
(let*
((temp (u8vector-ref sbox i))
(newj (u8+ j temp)))
(u8vector-set! sbox i (u8vector-ref sbox newj))
(u8vector-set! sbox newj temp)
(let
((val (u8vector-ref sbox (u8+ (u8vector-ref sbox i) temp))))
(write-char (integer->char (logxor (char->integer ch) val)))
(loop (u8+ i 1) newj)))))))
(define (do-crypt key iv rounds)
(crypt-loop (make-sbox (string-append key iv) rounds)))
(define (encrypt key rounds)
(let
((iv (call-with-input-file "/dev/urandom"
(lambda (port)
(setvbuf port _IOFBF 10)
(string-tabulate (lambda (i) (read-char port)) 10)))))
(display iv)
(do-crypt key iv rounds)))
(define (decrypt key rounds)
(let
((iv (string-tabulate (lambda (i) (read-char)) 10)))
(do-crypt key iv rounds)))
(define (main args)
(let*
((options (getopt-long args
`((key (single-char #\k) (required? #t) (value #t))
(rounds (single-char #\n) (value #t) (predicate ,string->number))
(decrypt (single-char #\d)))))
(key (option-ref options 'key #f))
(rounds (string->number (option-ref options 'rounds "20")))
(decrypt? (option-ref options 'decrypt #f)))
((if decrypt? decrypt encrypt) key rounds)))
Apparently the last Scheme posting was half a year ago, so let's have more!
Quick executive summary of the code: CipherSaber (http://ciphersaber.gurus.org/) uses Arcfour (http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt) for encryption, and the first 10 bytes of the encrypted file is the IV, which is appended to the user-specified key when keying the S-box.
I'm currently learning Scheme, and figure I could get some feedback on how to write more "idiomatic" Scheme programs...there are some things in my code at the moment that I'm not very happy with, like the "do" loop...I'm sure there's an analogue to Ruby "each" function that I'm yet to learn about. :-) I also don't see an easy way to avoid set!-ting j in the S-box setup loop...unlike in the main crypt loop.
There are also some Guile-isms in the code, like using logand/logxor without importing SRFI 60, getopt-long, and setvbuf. And Unixisms, like reading /dev/urandom. Apart from those, the code should be fairly "standard" R5RS.
2008-06-22T05:39:36+00:00
336
Lisp
ciphersaber
1
CipherSaber
2008-06-25T16:26:26+00:00
611
611
http://chris.jester-young.name/
Chris Jester-Young
4.3333
29
;; Turns a flat-list into a list of n-sized lists
;; Examples:
;; (group-by '(1 2 3 4) 2) => ((1 2) (3 4))
;; (group-by '(a b c d) 3) => ((a b c) (d))
;; (group-by '(a b c d) 1) => ((a) (b) (c) (d))
;; (group-by '(a b c d) 4) => ((a b c d))
;; (group-by '(a b c d e f 1 2 3 4 5 6) 7) => (a b c d e f 1) (2 3 4 5 6))
(define (group-by x n)
(let loop ((x x) (grouped '()) (current '()) (i 0))
(if (null? x)
(reverse (cons (reverse current) grouped))
(if (= i n)
(loop x (cons (reverse current) grouped) '() 0)
(loop (cdr x) grouped (cons (car x) current) (+ i 1))))))
Tested on MzScheme
2007-12-21T19:55:33+00:00
193
Lisp
group-by
5
Group-by
2008-06-29T09:33:18+00:00
424
424
http://omouse.vox.com
omouse.vox.com
0.0
0
; 5*O(n)
(defun next-lex (a)
(let* ((r (reverse a))
(pivot (first-down r)))
(multiple-value-bind
(less-pivot greater-pivot before-pivot) (partition-upto pivot r)
(nreverse (append (cdr greater-pivot) (list pivot) less-pivot
(list (car greater-pivot)) before-pivot)))))
; O(n)
(defun first-down (a)
(if (numberp (cadr a))
(if (> (car a) (cadr a))
(cadr a)
(first-down (cdr a)))
nil))
; O(n)
(defun partition-upto (pivot a)
(labels ((partition-sub (pivot a less more)
(cond
((eql (car a) pivot)
(values less (nreverse more) (cdr a)))
((> (car a) pivot)
(partition-sub pivot (cdr a) less (cons (car a) more)))
((< (car a) pivot)
(partition-sub pivot (cdr a) (cons (car a) less) more)))))
(partition-sub pivot a () ())))
;; > (next-lex '(1 3 5))
;; (1 5 3)
Given a list of numbers, generate their alphabetically next permutation.
Can this be shorter?
2007-10-04T00:19:44+00:00
55
Lisp
lexicographically-next-permutation
12
Lexicographically next permutation
2009-12-20T18:51:47+00:00
140
140
http://akkartik.livejournal.com
Kartik Agaram
0.0
4
http://akkartik.name
(defun transpose (m)
(cond
((null (car m)) nil)
(T (cons (mapcar 'car m) (transpose (mapcar 'cdr m))))
))
(transpose '((1 2 3) (4 5 6) (7 8 9)))
simpler? shorter?
2007-10-03T11:12:52+00:00
53
Lisp
matrix-transpose
5
matrix transpose
2008-05-23T21:58:33+00:00
64
64
http://mrsheep.myopenid.com/
mrsheep
0.0
0
(defun header-encode (string)
(if (find-if (lambda (c) (> (char-code c) 127)) string)
(format nil "~{ =?utf-8?B?~A?=~%~}"
(cl-ppcre:split #\Newline
(cl-base64:usb8-array-to-base64-string
(portable-string-to-octets string)
:columns 40)))
(format nil " ~A~%" string)))
(defun mail-headers (to from subject mime-type)
(format nil "To: ~A
From: ~A
Subject:~AContent-Type: ~A;charset=utf-8
" to from (header-encode subject) mime-type))
(defun better-mail-headers (to from subject mime-type)
(format nil "To: ~A
From: ~A
Subject: ~A
Content-Type: ~A;charset=utf-8
" to from (header-encode subject) mime-type))
I would like to use header-encode without needing to squeeze out the whitespace, as in better-mail-headers
2007-10-02T11:37:11+00:00
45
Lisp
folding-of-non-ascii-long-header-fields-rfc2822-section-2-2-3
2
folding of non-ascii long header fields (rfc2822 section 2.2.3)
2007-10-02T11:37:11+00:00
121
121
http://luser.myopenid.com/
luser.myopenid.com/
0.0
1