PDA

View Full Version : Racket



danbaron
28-02-2011, 03:43
Racket (in the Lisp family), seems to me to be, a nice language.

http://www.racket-lang.org/

It was formerly called, PLT Scheme.

http://racket-lang.org/new-name.html

The IDE is called, DrRacket.

From within DrRacket, you can edit programs, and also can interact directly with Racket, from a command prompt.

Racket programs are compiled executables.

I found some little tricks about it, not much.
Here is a Racket program that shows what I found.

#lang racket
(require racket/set)

(define s (set 1 2))
(set-member? s 1)

(define (dog b) (* b b))
(define (cat a c) (a c))
(cat dog 4)

(define ht (make-hash))
(hash-set! ht "apple" (cat dog 5))
(hash-ref ht "apple")

(define (ant) 2)
(set! s (set-add s "bird"))
(set! s (set-add s ant))
s
Concerning the program:

Line 1: tells the system that the language is Racket. DrRacket can also run some other languages.
Line 2: imports the module that contains set operations.
Line 4: defines a set, "s", with members, 1 and 2.
Line 5: asks if 1 is a member of s (output = #t, (shown below)).
Line 7: defines a function, "dog", which takes one parameter, "b". The function returns b squared.
Line 8: defines a function, "cat", which takes two parameters, "a", and "c". The way the body of the function is written, "(a c)", means that "a" must be a function which takes one parameter, c.
Line 9: calls the function, cat, with the parameters, dog, and 4 (output = 16, (shown below)).
Line 11: defines a hash table called, "ht".
Line 12: sets the key/value pair, "apple", and, "(cat dog 5)".
Line 13: retrieves the value for apple (output = 25, (shown below)).
Line 15: defines a function, "ant", which takes no parameters, and returns the value, 2.
Line 16: adds "bird" to s (The command, "set!", has nothing to do with sets, it means, "change the value of the previously defined variable".).
Line 17: adds ant to s.
Line 18: outputs s (output = (set 1 2 #<procedure:ant> "bird"), (shown below)).

The output from running the program is: -->

#t
16
25
(set 1 2 #<procedure:ant> "bird")

You can see from the output for s, that a set can contain a function (procedure). So, I think there must be a way to call the function indirectly, by accessing the set. But, so far, I don't know how.

:p

zlatkoAB
28-02-2011, 15:21
Dan...
i was wondering ,what you find so interesting in Lisp and derivates?
IF i understand correctly Lisp is in first place functional language?
And what would be advantage using lisp for hoby programmer?

danbaron
28-02-2011, 22:06
(Answer to Aurel = here)

For sure, part of my interest is because of boredom, curiosity, and novelty. Everyone likes new things.

(I am not an expert on this subject. These are only my spontaneous opinions.)

Simple computer languages are easy to learn and begin using. You can begin programming in 5 minutes. You just start telling the computer what to do. "A = this", "B = that", "print A", etc. You give the computer a sequence of instructions to follow, and the computer performs them in the order you specify. Simple computer languages don't require much documentation, and they don't take long to master.

More complex computer languages are not so straightforward. It can take a beginner a lot longer to be able to learn how to perform simple tasks. So, whether a person perseveres in learning a more complex language depends a lot on his motivation. Some people immediately become frustrated and quit, when they realize that they cannot quickly determine how to do a task that would be very easy in a simpler language. Other people just like to learn new languages, and they push ahead. For them, that is motivation enough. Others, want to write a particular type of program which they have found to be difficult, impossible, or awkward in simpler languages. In that case, they experience frustration when attempting the implementation in a simpler language, and are driven to try more complex languages in order to attempt to relieve their frustration. The more complex a language is, the more documentation it requires. Many books may be written describing different facets of the same language.

I can give some analogies of how I view simple versus complex computer languages. When you write a program, you first tell the language what you want to do, and then, it tells the computer, and the computer does it. Instead of telling the language, we can imagine that we tell a man, and then the man relays our instructions to the computer. If the man we are telling has a simple mind, then, we can only tell him simple instructions to relay to the computer, because those are all he can understand. If the man has a complex mind, then, we can tell him more complicated instructions, and he will be able to transmit them correctly to the computer. To me, a language is like a brain between you (the program's composer) and the computer. A small, simple brain, has a simple understanding and vocabulary, and can only transmit simple instructions. If you want to perform some complicated procedure, then, you must tell it a long sequence of simple instructions. A large, complex brain has a more sophisticated understanding and a larger vocabulary. Each instruction you tell it can contain more details about what you want to do. The result is that for a specific task that reaches some threshold level of complexity, it will require less work on your part to tell the complex brain, than to tell the simple brain - in other words, your program will be shorter. Additionally, and maybe paradoxically, the instructions for the complex brain will appear to an observer as being simpler than those for the simple brain, because the complex brain can understand a higher level of abstraction. Additionally, using the complex brain, you will be able to cause the computer to perform some tasks which it would be impossible for the simpler brain to cause the computer to do, because the simpler brain is not smart enough.

The languages that we are accustomed to using are called, imperative. Another type of language, which you mentioned, is called functional. I don't have any great knowledge, but, I think that functional languages originated in the academic world. It is clear to me that functional languages are initially more difficult to learn than imperative languages. But, I suspect that using functional languages can make implementing complex programs easier. So, I guess my opinion is that it is probably easier to do simple things using imperative languages, and, it is probably easier to do complex things using functional languages.

In the Racket code above, you can see that functions can be passed as parameters to other functions, a function can be the value of a hash table's key, and, a function can be a member of a set. My guess is that any object can be a member of a set, including a hash table. I hardly know anything about Racket, but, what I have found, is interesting to me.

Concerning Haskell, which seems to me to be the most sophisticated current language, you can find lots of examples where its implementation of a particular algorithm is much much shorter than a corresponding imperative language implementation, for instance, the quicksort. (Interestingly, in Haskell, if I am correct, it doesn't matter in which order a program's statements are executed!)

The other type of language which I have been looking at, is called stack-based, or concatenative. I think this type began with Forth. The dialect I have been looking at, is Factor (at the suggestion of Lance Gary). The latest version is 0.94. It comes with a big help system. But, I think it is pretty hard to learn. To me, using the help system to try to learn it, is similar to using a dictionary to try to learn a human language. In other words, most of the references in the help system are circular. Just like in a dictionary, each word is defined in terms of other words in the same dictionary. If you don't understand any of the words at all, then, it can be almost impossible to get started. Additionally, when I use the help system's search feature, the program crashes. I'm not saying there is anything wrong with Factor itself, I'm just complaining about using its help system in its current form, in order to try to learn the language. Beyond that, as I said before, so far, I don't see what the great benefit is of putting parameters on the data stack in order to pass them to functions. Probably there is more there, about which, so far, I am ignorant.

One more thing about Factor. It seems to me that the only way it might be possible to learn a language by using only a dictionary, is if the dictionary contained some words which were not defined in terms of other words. I guess that they could be defined by pictures. Similarly, I think that Factor needs more example code, for people who are trying to learn it, but, who know absolutely nothing about it.

Finally, you know that whenever you learn something new, your brain makes more circuits and connections, and, you become smarter. So, the more computer languages you try to understand, the easier it becomes to understand the next one.

:p

zlatkoAB
01-03-2011, 12:38
Heh i guess that your answer will be big;)
Im not sure but this expression 'functional' is little bit stupid for me.
What that means?
Is that mean that basic is disfunctional?
If you want see something really new look into seed7...

zak
01-03-2011, 17:41
there is also esoteric (Bizarre) programming languages i hope i will look to some day, Dan you may find it interesting:
http://www.dangermouse.net/esoteric/

Chef is a stack-based language where programs look like cooking recipes:
http://www.esolangs.org/wiki/Chef

Top 10 Truly Bizarre Programming Languages:
http://listverse.com/2011/02/17/top-10-truly-bizarre-programming-languages/

www.ponselcina.com/article/pi--esolang.htm

and most of those are made from C programming language like most other languages
and do not forget the future quantum computing programming for the future quantum computers which may be sold as laptops in the year 2111, i wonder what OS will operate those semi alive instruments, and what web speed will be then, but sure it is instantaneous and 3D youtube. big screens, and may be virtual reality .wonderfull.
other References:
http://en.wikipedia.org/wiki/Esoteric_programming_language
http://esolangs.org/wiki/Language_list

Petr Schreiber
01-03-2011, 19:47
Hi Zlatko,



Im not sure but this expression 'functional' is little bit stupid for me.
What that means?
Is that mean that basic is disfunctional?
I think this might be problem of "translation". The "functional programming" does not mean it is "has better functionality than others", but instead, the word "functional" is related to big focus on use of functions for ... everything. On Wiki (http://en.wikipedia.org/wiki/Functional_programming) it is defined as:


In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids state and mutable data
It is simply "different approach". Very exciting as mental practice, less exciting for real use sometimes :) In the start of the course at University I thought functional programming comes directly from hell, but with the time I must admit it has some of ellegant moments. But also lot of possible problems - recursion is very cool, yet it is usually slower approach than pure looping for example.


Petr

danbaron
02-03-2011, 09:52
Aurel, I agree with Petr, functional programming can at first appear to be a misery.

Imagine if you say,

a = 2

Then, later you say,

a = 3

If I'm correct, then, guess what?, you just got an error message. Unless I'm mistaken, you cannot change a variable's value.

Anyway, I think that as of now, Haskell is the king of functional programming languages. You can download it here.

http://www.haskell.org/haskellwiki/Haskell

There's a lot there, because the download is 74 MB, and that's without an IDE.

Once you install it, you can open a console window and enter, "ghci" (Glasgow Haskell Compiler Interactive). Then you will be at the interactive prompt, and you can start experimenting.

Here is a good tutorial that uses GHCI.

http://en.wikibooks.org/wiki/Haskell

Just start the tutorial at the beginning, it's easy. It starts in very shallow water. But if you follow it far enough, you'll find yourself floating alone on the rolling waves, in the middle of the ocean.

But, don't be afraid, if you drown, it will only be virtual!

(I will have to look at the languages zak enumerated, and also, seed7. If they make quantum computers, then, I hope I can teleport myself into a better universe.)

:idea:

zlatkoAB
02-03-2011, 21:21
Dan
Did you ever tried Harbour?
Looks very interesting ....

danbaron
02-03-2011, 22:32
I didn't know about it.

I just looked now.

http://en.wikipedia.org/wiki/Harbour_(software)

http://www.harbour-project.org/

I agree, it looks good.

And, it is open source, which, to me, is a big positive.

And, it comes with an IDE, which, to me, is another big positive.

"Harbour has 6 scalar types : Nil, String, Date, Logical, Number, Pointer, and 4 complex types: Array, Object, CodeBlock, and Hash."

Variables have four possible scopes.

It has modules, and OOP.

"One of the most powerful features of xBase languages is the Macro Operator '&'. Harbour's implementation of the Macro Operator allows for runtime compilation of any valid Harbour expression. Such a compiled expression may be used as a VALUE, i.e. the right side of an assignment (rvalue), but more interestingly, such a compiled expression may be used to resolve the left side (lvalue) of an assignment, i.e. PRIVATE, or PUBLIC variables, or a database FIELD.

Additionally, the Macro Operator may compile and execute function calls, complete assignments, or even list of arguments, and the result of the macro may be used to resolve any of the above contexts in the compiled application. In other words, any Harbour application may be extended and modified at runtime to compile and execute additional code on-demand.

Latest Macro compiler can compile any valid Harbour code including code to pre-process before compile."

I am going to download it, version 2.0, 53.1 MB.

Hopefully, it will come with enough documentation to learn it.

:p

danbaron
20-03-2011, 11:48
(Timing Recursive Factorials)

Racket is a descendant of Scheme, which is a dialect of Lisp.

Lisp likes to use recursion to do things.

I previously used the LispWorks implementation of Common Lisp, to time a recursive factorial function.

I tried doing it with Racket.

I made the following file in the DrRacket IDE.


#lang racket

(define (fac n)
(if (< n 2)
n
(* n (fac(- n 1)))))

(define (time-fac n)
(let ([t1 (current-inexact-milliseconds)])
(fac n)
(let ([t2 (current-inexact-milliseconds)])
(print (/ (- t2 t1) 1000)))))
(Note, that in the code, the built-in function name, "current-inexact-milliseconds", is misleading. "inexact" appears in the name, because the function result may contain fractions of a millisecond.)

I saved it, and then ran it from within DrRacket.

When you run a file that only contains function definitions, DrRacket just compiles and loads it.

Then, the functions are available to use from the DrRacket REPL (read-eval-print loop).

Next, from the REPL, I timed the recursive factorial function, "fac", for different values.

Here is my interaction with the REPL (the times are in seconds).

Welcome to DrRacket, version 5.1 [3m].
Language: racket; memory limit: 128 MB.
> (time-fac 4096)
0.062
> (time-fac 8192)
0.499
> (time-fac 16384)
4.446
> (time-fac 32768 )
9.126
> (time-fac 65536)
52.588
>

It seems pretty amazing to me, that even for 65536, Racket didn't complain, and calculated the result in less than a minute. That's for a recursion level of 65535. I can't imagine how many digits that factorial contains.

:!:

danbaron
21-03-2011, 07:41
In the previous post, I said that I couldn't imagine how many digits 65536! (65536 factorial) contains.

Now, I can imagine how many, because, I figured out one way to determine how many (probably not the easiest way).

Anyway, after again running (compiling and loading) the same file as shown in the previous post, here is my interaction with the REPL, which yields the number of digits in 65536!.

Welcome to DrRacket, version 5.1 [3m].
Language: racket; memory limit: 128 MB.
> (define big-fac (fac 65536))
> (define big-fac-string (number->string big-fac))
> (define big-fac-list (string->list big-fac-string))
> (define big-fac-digits (length big-fac-list))
> big-fac-digits
287194
>

So, 65536! contains 287194 digits. If you assume that you can fit 4000 digits (80 digits per line, times 50 lines) per page, then, it would require approximately 72 pages to print out the value of 65536!.

:?:

jack
21-03-2011, 18:29
Dan, perhaps you are off by one digit?
here's way to calculate the number of digits of large factorials,
it's based on the series expansion of the logGamma function for large numbers
logGamma(x) = x (-log(1/x) - 1) + 1/2 log((2 Pi)/x) + 1/(12 x) - 1/(360 x^3) + 1/( 1260 x^5) ...


#lang racket
(define (fac-digits n)
(define n1 (+ 1 n))
(define pi 3.141592653589793)
(define log10e 0.434294481903252)
(inexact->exact (ceiling (* log10e (+ (* n1 (- (log n1) 1)) (* 0.5 (log (/ (* 2 pi) n1))))))))

(fac-digits 65536)

danbaron
21-03-2011, 21:40
Unfortunately for me, I'm not a mathematician, Johan.

I verified that your way gives 287193! (<-- exclamation point, not factorial).

Could the reason for the discrepancy be found in the following quotation?

In mathematics (http://en.wikipedia.org/wiki/Mathematics), the Gamma function (represented by the capital Greek (http://en.wikipedia.org/wiki/Greek_alphabet) letter Γ (http://en.wikipedia.org/wiki/Gamma)) is an extension of the factorial (http://en.wikipedia.org/wiki/Factorial) function (http://en.wikipedia.org/wiki/Function_%28mathematics%29), with its argument shifted down by 1, to real (http://en.wikipedia.org/wiki/Real_number) and complex numbers (http://en.wikipedia.org/wiki/Complex_number).

http://en.wikipedia.org/wiki/Gamma_function

Now I have to hurry for my train.

Maybe more later, if I can think of something else.

But anyway, you've tried Racket. Pretty good version of Scheme, yes?

:bom:

jack
21-03-2011, 22:29
Dan, your numbers were right, I fixed my function above.
I agree, DrRacket is a nice environment to experiment in programming. :)

danbaron
22-03-2011, 07:06
I don't know where you got that series, Johan, but, I think I see what you did.

If I understand correctly,

logGamma(x) = log10(Gamma(x)) .

I think you knew you couldn't calculate Gamma(65536), because, the Racket answer would be "inf". So, instead you used the series to simultaneously calculate both log and Gamma, thereby avoiding overflow. If true, then, very smart.

:yes:

jack
23-03-2011, 02:37
Dan, I got the series using Mathematica, but should be simplified a bit
instead of logGamma(x) = x (-log(1/x) - 1) + 1/2 log((2 Pi)/x) + 1/(12 x) - 1/(360 x^3) + 1/( 1260 x^5) ...
it should be logGamma(x) = x (log(x) - 1) + 1/2 log((2 Pi)/x) + 1/(12 x) - 1/(360 x^3) + 1/( 1260 x^5) ...
because -log(1/x) = log(x).

danbaron
23-03-2011, 07:39
I agree, -log(1/x) = log(x).

And, you got the correct answer using only two terms. I guess, probably if gamma(x) was big enough, you would have to include more terms.

I think there is one case for which your formula will not work. It concerns your use of the function, "ceiling". I think it won't work in the case that,

m! = 10^n (where m and n are integers).

I don't know if such a case exists. Anyway, you can see how your method can give the wrong answer. For instance, if gamma(x) = 10^2 = 100, then, ceiling(log10(gamma(x)) = 2, but, 100 has 3 digits.

:evil5:

jack
24-03-2011, 04:34
Dan, you are right, but if you know the number of binary bits of the number then you can get the number of decimal digits by this formula: DecimalDigits = ceiling(NumberOfBits*log10(2))

danbaron
24-03-2011, 06:47
I think the general case is,

DecimalDigits = ceiling ( NumberOfBits * logA (2) / logA (10) ), <-- (for any base, A).

When A equals 10,

logA (2) / logA (10) = log10 (2).

Good enough.

:unguee:

danbaron
02-04-2011, 09:05
Racket is a descendant of Scheme, which is a dialect of Lisp.
In Racket, and generally in Scheme, a procedure is a, "first class object".
I think it means that anything you can do with a variable, you can do with a procedure.

As shown in the code, you can pass a procedure as a parameter to another procedure.
And, you can make a list of procedures, and call a procedure if it belongs to a list.

:bom:


; Program -------------------------------------------------------

#lang racket

; Procedure e, takes a procedure as a parameter.
(define (e g m) (g m))

; Will pass procedure f to procedure e, below.
(define (f n) (* n n))

; Define procedures, g, j, k, m.
(define (g x y) (* x y))
(define (j x y) (+ (* x x) (* y y)))
(define (k x y) (- (* x x) (* y y)))
(define (m x y) (* (* x x) (* y y)))

; Define a list l, containing procedures g, j, k, and +.
; Notice that the operator +, is just a procedure like any other.
(define l (list g j k +))

; Pass the procedure f to procedure e.
(e f 2)

; Check if a procedure is in the list, l. If it is, then, call the procedure.
(if (member g l) (g 6 7) "Sorry. Procedure is not in the list.")
(if (member j l) (j 6 7) "Sorry. Procedure is not in the list.")
(if (member k l) (k 6 7) "Sorry. Procedure is not in the list.")
(if (member + l) (+ 6 7) "Sorry. Procedure is not in the list.")
(if (member m l) (m 6 7) "Sorry. Procedure is not in the list.")



; Output --------------------------------------------------------
; (This is the output when the program is run from within the REPL (read-eval-print loop)).

4
42
85
-13
13
"Sorry. Procedure is not in the list."
>