Last active
March 5, 2017 18:55
-
-
Save lispm/63a50e07de78a59bdf3e053ebe7abb67 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; https://z0ltan.wordpress.com/2017/02/24/a-piglatin-translator-in-common-lisp-and-contrasting-it-with-the-racket-version/ | |
#| | |
(defpackage #:piglatin | |
(:use :cl :cl-user)) | |
; using CL-USER makes no sense, it usually does not export anything. | |
(in-package #:piglatin) | |
(defun translate (sentence) | |
(let ((*readtable* (copy-readtable nil))) | |
(setf (readtable-case *readtable*) :preserve) | |
(mapcar #'make-symbol | |
(mapcar #'english-to-piglatin | |
(mapcar #'string-to-list | |
(mapcar #'symbol-name sentence)))))) | |
; Why use a readtable, when you don't read? The readtable has no effect at all. | |
; The function is called with a list of symbols. Thus they are already read. | |
; Nested mapcars? Not really. | |
; --- | |
; In plain Lisp, instead of: | |
(mapcar #'make-symbol | |
(mapcar #'english-to-piglatin | |
(mapcar #'string-to-list | |
(mapcar #'symbol-name sentence)))) | |
; use: | |
(mapcar (lambda (symbol) | |
(make-symbol | |
(english-to-piglatin | |
(string-to-list | |
(symbol-name symbol))))) | |
sentence) | |
; or: | |
(loop for symbol in sentence | |
collect (make-symbol (english-to-piglatin (string-to-list (symbol-name symbol))))) | |
; --- | |
(defun english-to-piglatin (word) | |
(if (starts-vowel-p word) | |
(word-to-vowel-rule word) | |
(word-to-consonant-rule word))) | |
(defun starts-vowel-p (word) | |
(member (char-downcase (car word)) '(#\a #\e #\i #\o #\u #\y))) | |
; A word as a list? Use strings. | |
(defun word-to-vowel-rule (word) | |
(coerce (append word '(#\w #\a #\y)) 'string)) | |
; A word as a list? Use strings. | |
(defun word-to-consonant-rule (word) | |
(let ((was-capital-p (upper-case-p (car word)))) | |
(labels ((f (word) | |
(if (starts-vowel-p word) | |
(cond (was-capital-p (string-capitalize | |
(coerce (append word '(#\a #\y)) 'string))) | |
(t (coerce (append word '(#\a #\y)) 'string))) | |
(f (append (cdr word) (list (char-downcase (car word)))))))) | |
(f word)))) | |
; A word as a list? Use strings. | |
; Get rid of the recursion, too. | |
(defun string-to-list (word) | |
(coerce word 'list)) | |
; A word as a list? Use strings. | |
|# | |
; basic rules | |
; * don't convert strings to lists | |
; * readtables have no effect on already read symbols | |
; * create more useful basic functions | |
; * don't use nested mapcars | |
; * basic functions should not take one data structure and return another, until necessary | |
; if it gets a string, return a string. | |
; if it gets a list, it should return a list | |
; if it gets a symbol, it should return a symbol | |
; | |
; optional | |
; * replace symbols with strings | |
; basic meta rule | |
; * if the Common Lisp code looks quirky, then it is possibly non-idiomatic | |
; a more idiomatic version | |
(defun vowel-p (char) | |
(find char "aeiouy" :test #'char-equal)) | |
(defun starts-with-vowel-p (word) | |
(vowel-p (aref word 0))) | |
(defun capital-p (word) | |
(upper-case-p (aref word 0))) | |
(defun word-vowel-rule (word) | |
(concatenate 'string word "way")) | |
(defun word-consonant-rule (word) | |
(let* ((pos (or (position-if #'vowel-p word) (length word))) | |
(new-word (concatenate 'string (subseq word pos) (subseq word 0 pos) "ay"))) | |
(if (capital-p word) | |
(string-capitalize new-word) | |
new-word))) | |
(defun english-to-piglatin (word) | |
(if (starts-with-vowel-p word) | |
(word-vowel-rule word) | |
(word-consonant-rule word))) | |
(defun translate (sentence) | |
(loop for word in sentence | |
collect (intern (english-to-piglatin (string word))))) | |
; (translate '(|Hello| |world| |we| |meet| "again")) | |
; -> (|Ellohay| |orldway| |eway| |eetmay| |againway|) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment