Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

Common Lisp for Schemers

Name: fag 2013-12-29 0:49

What's the best way for a Schemer to learn Common Lisp? It seems like Scheme itself is a more beautiful language, but the efforts made by many implementations to make Scheme useful "in the real world" lead to a big ball of mud™. Does Common Lisp avoid this problem? Should I keep trying to learn different Scheme implementations instead until I find something I like?

Name: Anonymous 2013-12-29 0:54

install gentoo

Name: Anonymous 2013-12-29 0:57

>>2

(let loop ()
  (display "thanks\n")
  (display ":^)")
  (loop))

Name: Anonymous 2013-12-29 1:01

>>3
Scheme:
(let loop ()
  (display "thanks\n")
  (display ":^)")
  (loop))


Haskell:
loop = putStrLn ("thanks\n" ++ ":^)") >> loop

Name: Anonymous 2013-12-29 1:05

>>4
Scheme:

(define-syntax lett
  (syntax-rules ()
    ((_ exp) exp)
    ((_ k v rest ...)
     (let ((k v))
       (shen-let rest ...)))))

(lett x "fuck" y (string-append x " you\n") (display y))

Your move, Haskell wankers.
Just kidding. I love all of you.

Name: Anonymous 2013-12-29 1:15

>>5
Haskell:
putStrLn "fuck you"
:^)

Name: Anonymous 2013-12-29 1:16

>>6
>tfw you don't even understand macros
Come on Haskellers, step it up.

Name: Anonymous 2013-12-29 2:32

>>1

A Schemer learns Common Lisp just like anyone else learns Common Lisp: Reading "Practical Common Lisp" and the Hyperspec, then supplementing that with practice and other books (I recommend PAIP).

When you learn Common Lisp, or any language for that matter, it is imperative that you do not compare it or look for similarities with other languages you know. Pretend you are learning your first language.

Only once you have mastered the langauge does it make sense to compare it with other languages you have mastered.

Name: Anonymous 2013-12-29 6:34

>>1
No, Common Lisp does not evade this problem. It is much more beautiful than Scheme (particularly its macros, its condition-return system, and its CLOS and MOP), but still a huge ball of mud and crutches. Common Lisp hasn't changed since the nineties and is a very old and antiquated language.
Quit Lisp and learn a real world language instead.

Name: Anonymous 2013-12-29 6:51

>>7
Macros are just a source of bugs. It's like fucking copy, paste and replacing pieces of text. Your example is naturally done without dirty referentially opaque tricks: just use a reader monad. It's just that I'm too lazy to do it myself..

Name: Anonymous 2013-12-29 8:24

>>10

Lisp macros do not replace text.

Name: Anonymous 2013-12-29 8:30

>>9

Common Lisp is not antiquicated at all.

The latest C++ standard was in 2011. One of the features was lambdas.

Most languages, their tools, and their implementations have not caught up to Common Lisp. I know of only two things which have exceeded Common Lisp: The Java Hotspot features concurrent GC, and Mathematica has something similar to presentations but a bit nicer (but, obviously, not all ubiquitious like on a Lisp machine).

Everything else is behind.

Name: Anonymous 2013-12-29 8:36

>>10

You don't know what "referentially opaque" and for that matter "referentially transparent" means. You are repeating a meme. You don't actually understand what you are saying, you are just saying it cause someone else did.

Name: Anonymous 2013-12-29 8:57

>>13
Read Strachey (1967) you uneducated fuck. I know exactly what referential transparency is and why macros break it.
Here is a good discussion to get you started: http://stackoverflow.com/questions/210835/what-is-referential-transparency

Name: Anonymous 2013-12-29 9:30

>>14
O, sage, may you please shed light on why are macros referentially opaque after expansion, in principle?

Because as far as I'm reading, I don't believe you shit.

Name: Anonymous 2013-12-29 10:59

>>15
Macros do not exist after expansion, you dimwit. The whole point of a macro is to avoid writing the code that it will expand to. So the code that you write will be referentially opaque. And that can be considered an advantage and certainly can look witty (as in anaphoric macros) but ultimately for large projects it turns into a hassle as having a clear decomposition basis for your code is better than saving a couple of lines with witty macros.

Name: Anonymous 2013-12-29 12:15

>>16
That was the point, you self-important buffoon. Macros are nothing but functions which transform an expression into another. I don't see any difference with regards to referential transparency than any other arbitrary syntactic rule.

And if you reduce macros' utility to merely "saving a couple of lines", then you haven't understood them. Or like Python, but both cases overlap.

Name: Anonymous 2013-12-29 12:47

Macros aren't just functions, they're functions that act on terms of code and that's exactly why they can create a referentially opaque context for your term. You want an example? Here you have it:

(defmacro referentially-opaque-context (&body body)
  `(let ((it -1))
     ,@body))

(defun foo ()
  (let ((it 1))
    (referentially-opaque-context
      (+ it 1))))

Thanks to referential opaqueness, we have 1+1=0. If we had renamed the variable into something other than "it", we would have our 1+1=2 back. The semantics of the code term "(+ it 1)" changes depending on the choice of reference. Now go bother someone else with your ignorance.

Name: Anonymous 2013-12-29 13:09

>>18
Yes, it's well known that anaphoric macros are referentially opaque like that. That just makes them referentially opaque in general, but not generally. You could say the same about functions, some of which may alter external state. Anaphoric macros are, in any case, a novelty used used by a few Common Lisp programmers, most notably Paul Graham.

Your pedantic diatribes are unconvincing, but do go on if you wish, I'm patient.

Name: Anonymous 2013-12-29 13:33

>>19
The thing is, you cannot tell just by looking at a piece of code, whether the macros used in it are of the generally sort or the in general sort. They all might alter the meaning of code in unpredictable ways, and that was just a simple example. Macros introduce hidden mutations just like functions which alter external state introduce mutations: macros mutate your code and impure functions (aka procedures) mutate your state, and all of that is done in a furtive, unobvious way.
This is what makes both macros and impure functions evil - they introduce extra mutation pathways that make your code less obvious, less modular, harder to test and harder to decompose. With macros you can't tell what code is hidden behind a given piece of code, and with impure procedures you can't tell what actions are hidden behind a piece of code. Putting macros and impure functions into one language makes for a Molotov cocktail. Isn't that why many Lispers (including the aforementioned Paul Graham, Rich Hickey and the "Land of Lisp" guy) advocate a functional style? Except that Common Lisp isn't made for functional style, so they are stuck with Clojure which is a Javahaskell more than it is a lisp.

Name: Anonymous 2013-12-29 17:02

>>20

Look,

Consider (+ 3 x)

I know almost nothing about it. I don't know if a given compiler will accept it, that depends on the compiler. I have no idea what kind of machine code that compiler will produce.

Making some assumptions (e.g. some kind of Lisp reader and compiler (or interpreter) and probably a million more tacit assumptions) I can say that + is a "function", I can say that x is a variable that can be "bound", I can say that 3 represents something like a number (but really, not really).

Even with these assumptions I have no idea what this program does. I do not know how + is defined. For all I know it could sort lists. I have no idea what x is bound to, it could be a string.

There is no way whatsoever to tell what (+ 3 x) means without more assumptions, without some sort of contextual information.

It is impossible.

Now, in the same way I actually, really, truly do know many things about +, 3 and x in Common Lisp, my Common Lisp implementation, the machine it runs on, and the particular part of program text in my program it appears (due to the huge amounts of contextual information I have absorbed) I can understand (+ 3 x).

This is no harder or easier for me to understand than the fact that within the body of (aif ... ) the vairable it will be bound to the first form evaluated.

It requires a very similar amount of contextual information to understand when reading the program. It requires the same amount of reasoning, and it requires the same amount of checking to make sure I understand what it really means.

No amount of meme repetition by you or anyone else can change these facts.

Name: Anonymous 2013-12-29 17:25

>>20

What makes Clojure a "Javahaskell"?

Clojure is nothing like Haskell. Clojure has subtyping, Haskell doesn't. Haskell uses normal order of evaluation, while Clojure is applicative. Clojure's syntax is nothing like Haskell's syntax.. etc. etc. etc. etc.

The differences are so vast that I have no idea how you or anyone else can make this kind of statement.

Also I have no idea why Paul Graham (not a Lisp programmer, but an Arc programmer (always had a Scheme bent)) and Rich Hickey (again not a Lisp programmer, but a Java/C++ programmer who learned and briefly used Lisp and then became Clojure programmer) and Conrad Barski (Again, a Java programmer who learned Lisp and then moved on to Scheme and Clojure) advocate a "functional style" (what does this even mean? Actually, I know what you think it means but why do you want it to mean that? It is a very stupid definition). What I do know is that they are not Lisp programmers.

I don't really know of any real Lisp programmers that "advocate" any particular style . This is one of the hallmarks of a Lisp programmer. Indeed, I write programs using go and tagbody and programs using do and programs using defclass and programs using lambda. I don't advocate you write your programs in any particular way. I advocate that you understand the programs you write, the tradeoffs made in expressing them the way you did, and the ability to justify why you wrote your program in the way you did.

Name: Anonymous 2013-12-29 18:15

>>21
If you go down that route, a mess of pointers and malloc's with side effects everywhere should pose no difficulty to a Real Programmer. It's subtler than that, and that's a subtlety that a Common Lisp programmer should grasp, using a language which compromised the concerns of every implementor of Lisp languages at the time.

On a side note: Google no longer presents me captchas with house numbers, why is that? Is my IP/cookie "trusted" now? Is it because I fed it with randomly generated numbers?

Name: Anonymous 2013-12-29 18:18

>>23
>le pedophile sage

Name: Anonymous 2013-12-29 18:32

>>24
>le pedophile sage

Name: Anonymous 2013-12-29 19:12

OP here, thanks for the read. <3

>>8
Thanks for this, I'll pick up the book sometime. I don't really care if the language is antiquated, I already like Lisps enough that I feel like I should learn it.

Name: Anonymous 2013-12-29 19:40

>>26

A substantial amount of Common Lisp classics are available online for free (legally) and an even larger amount ilegally.

http://www.gigamonkeys.com/book/

Name: Anonymous 2013-12-29 20:14

>>23

I have a longer reply but, in short:

+ Pointers (as they appear in C i.e. with pointer arithmetic) aren't useless.
+ You do lose something when you lose pointers (especially in C)
+ Understanding programs that use pointers is not a problem and is not macho or special.
+ Understanding, identifying, and decorating "problem spots" with regards to pointers in C is not hard e.g. you should know how to analyze loops, memory bounds etc.
+ The problem isn't that it's hard to do the above, it's that it is annoying to do it all the time and constantly being aware of it: There is no easy way to abstract and automate this in C!
+ More simply, C sucks at metaprogramming.
+ Ironically, pointers are the one thing in C which helps with (runtime) metaprogramming (self modifying programs, run time code generation, intercession etc.), but not by themselves.
+ There are much more pleasant and less round about ways to do metaprogramming (e.g. how Common Lisp and Smalltalk do it).
+ With regards to systems programming and security; both depend more on physical reality rather than language features (C, Common Lisp, Smalltalk implementations etc. all allow you to inline assembly and that's that).

Name: Anonymous 2013-12-29 20:23

>>28
There would be no problems with either pointers or inline assembly if the machine had tagged memory or object-level permissions.

Name: Anonymous 2013-12-29 20:40

>>29

I do not know if you are correct. However, I my intent was to imply strategies at the machine level (not unlike the ones you mentioned) (and other levels) when I said "physical reality".

Name: Anonymous 2013-12-29 22:15

>>28
+ You do lose something when you lose pointers (especially in C)
What do you lose?

A quick question first: are you aware that The Standard says that pointer arithmetic resulting in out of bounds values is undefined behaviour (section 6.5.6.8)? Or are you one of those script kiddies who have not even read The Standard and whose notions of what C language is would rather fit a high fantasy novel, as indicated by your mention of "self modifying programs"?

Name: Anonymous 2013-12-30 0:52

>>31

Yes I am aware.

There is nothing "high fantasy novel" about writing self modifying programs.

First allocate some memory. Now get a pointer to that memory and write a program there. To "evaluate" that program either x86 JMP your way there (or equivalent inline assembler) or (, if your new program obeys the "host" (for lack of a better word) program's compiler's various conventions) cast the address to a function pointer. This is called run time (or dynamic) code generation. It's done all the time e.g. my Common Lisp implementation does it, as does the Hotspot JVM.

Now, If you want to change that program, then just write to that same memory. This is called "self modifying code".

If you want to specify the programs you write to that memory in some language, then you need to be able to compile that language. For example you may want to use libtcc if you wish to specify programs in C.

Now, because of "modern" operating systems you can't just allocate memory and have it be executable willy nilly; you have to ask first. If you are on Linux you want mman.h (specifically mprotect) and if you're on Windows you want Windows.h (specifically VirtualProtect). idk about other operating systems.

I should add in the case you want to modify the "host" program directly as it is in memory, you use function pointers or your compiler's equivalent of GCC's labels as values extension and then jump whatever hoops your operating system require you to.

Again, this is not esoteric, macho or arcane. It's just programming.

Name: Anonymous 2013-12-30 1:06

>>31

Now as for your question, "I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question"

Just kidding. Although it is an odd question.

The first thing that comes to mind is that you would lose the ability to allocate data structure dynamically, which is pretty important (if you need an example just think of a linked list or idk being able to read an unknown amount of images of unknown size from files at user request, I mean there's a million things you need dynamic memory for).

Name: Anonymous 2013-12-30 1:15

I should add that I interperted your question as "If you took pointers out of C what would you lose".

I don't know how to answer the question "If you took pointers out of any language what would you lose" because this depends on the language.

Name: Anonymous 2013-12-30 4:41

Only shitty languages have pointers. References are enough for real programming.

Name: Anonymous 2013-12-30 5:19

>>32
function0 :: A -> B -> C
main = do
 function1 <- return $ function0 x -- created a new function at runtime
 return $ function1 y -- called it at runtime

Name: Anonymous 2013-12-30 5:41

>>36

What on earth is your point?

Name: Anonymous 2013-12-30 5:49

>>37
That I can create and execute functions at runtime with just a couple of lines of code without needing to fuck with the OS.

Name: Anonymous 2013-12-30 6:46

>>38

Very nice, but (in this case) that's not the same as run-time code generation (which is what was being discussed). Indeed, no new programs are created at runtime by the snippet you displayed; everything is created statically, when your batch compiler (GHC) first batch processes your program.

Since you are a Haskell programmer maybe studying how to do run time code generation in your language, and contrasting it to that example of plain old static code generation you showed me will help you understand the difference? http://hub.darcs.net/stepcut/plugins

Today, a "lambda" or "closure" feature (or whatever your language calls it) in a language is hardly special. Many languages feature them today. Here are a few examples of something similar to what you showed me in Haskell in other languages off the top of my head:


;; In Common Lisp
(progn
  (let (silly)
    (setf silly (lambda (x) (* x x)))
    (funcall silly 4)))

"In Smalltalk"
[|silly|
  silly := [:x | x * x].
  silly value: 4.] value.

// In C++
auto silly = [](int i) { return i * i; };
int result = silly(i);


None of this is the same as run-time code generation. To contrast:

;; In Common Lisp.
(progn
  (let (silly)
    (setf silly (compile nil (read-from-string "(lambda (x) (* x x))")))
  (funcall silly 4)))

"In Smalltalk"
[|silly|
  silly := Compiler evaluate: '[:x | x * x]'.
  silly value: 4.] value.

// In C++
// Just kidding C and C++ provide pretty much only pointers
// for metaprogramming hence this whole discussion. Please
// read my earlier post on how to laboriously do run-time
// code generation in C.


Now notice the string in both examples could have come from some file, network, user input, or any other thing not knowable apriori, at compile time.

So hopefuly this sort of gives you some idea on what run-time code generation is and the topics discussed earlier.

Name: Anonymous 2013-12-30 6:59

>>39
This is just an open door for errors and insecurities. Why would you want to create code at runtime anyway? It's all going to be filled with bugs anyway.

Name: Anonymous 2013-12-30 8:02

>>32-34
There is nothing "high fantasy novel" about writing self modifying programs.
... in Standard C. All of it is high fantasy. Because inline assembly and calling a function pointer that doesn't represent a function are C equivalents of deep magic and travelling through a wardrobe.

The first thing that comes to mind is that you would lose the ability to allocate data structure dynamically
Today I learned that I can't allocate data dynamically in Python, or that it has pointers. OK, let me rephrase, what do you lose if you turn C pointers into references, i.e. get rid of pointer arithmetic (while making array indexing a first class operation, obviously)?

Name: Anonymous 2013-12-30 19:13

>>40

Mainly to implement an "extension" language (i.e. plugins, user scripts etc) (or make it more efficient for the interpertation case). Almost all large systems come with an extension language, and even desktop productivity programs (e.g. CAD, CAS, EDA, image editing, document preparation, music composition etc. etc.).

Another use is emulation.

I suppose you could argue that it's just an optimization technique cause you could just write an interpreter for everything.

In software computer graphics JIT generation of efficient functions is an overt use of dynamic code generation for optimization.

idk there's lots of uses for it. Use your imagination.

Name: Anonymous 2013-12-30 19:31

>>41

There's no travelling through wardrobes involved. And you don't have to use assembly.

Also, you learned no such thing. However you're onto something; while it might sound stupid to you Python variables are, indeed, similar to pointers in C. For example pass a Python variable to a function and then mutate it's value in some way. Now do the same in C. Now look at the value of the variable in the caller after return. Now do the same but using a pointer in C.

Comparing "pointers" "names" "references" "variables" etc. across languages is not usually useful, because these words mean subtly different things in each language's community. Compare the real meaning of "variable" in Common Lisp (a language with first class symbols with a number of "namespaces" (again this means something very different to a C++ programmer or a Modula programmer)) to what it means in C or even Java or even Scheme. The C community makes a distinction between "lvalue" and "rvalue" which isn't that common outside the C community. etc. etc.

You just have to come to terms that the same words are used to mean completely different things when refering to different programming languages.

Name: Anonymous 2014-02-08 8:16

check 'em

Name: Anonymous 2014-02-08 12:33

>>1
What's the best way for a Schemer to learn Common Lisp?

Read Paul Graham's ANSI Common Lisp, that is mostly an extract from SICP, adapted to realities of CL. You won't learn much new, but will see how CL relates to Scheme.

Name: Anonymous 2014-02-08 12:34

>>45
Oh, I forgot, it is the OnLisp - another PG's book. ANSI Common Lisp book is useless.

Name: Anonymous 2014-02-09 5:42

>>39
#include <cling/Interpreter/Interpreter.h>
#include <cassert>
#include <iostream>

int main(int argc, char** argv) {
    cling::Interpreter interpreter(argc, argv);
    cling::StoredValueRef sillyFunc;
    int result = interpreter.evaluate("[](int i) { return i * i; }", sillyFunc);
    assert(result == cling::Interpreter::kSuccess);
    int (*silly)(int) = sillyFunc.get().getAs<int(*)(int)>();
    std::cout << silly(4) << std::endl;
    return 0;
}

Don't change these.
Name: Email:
Entire Thread Thread List