I have been reading "The Little Schemer" in my spare time and trying to experiment with the syntax and I've come across a syntax issue I can't wrap my head around. I have a script that looks like this:
;;;; Chapter 2 examples
;;; Note: run this file with 'mit-scheme --quiet < c2.scm'
;; You can define variables using the "define" function
(define my-favorite-number 13)
;; You can define strings using double-quotes
(define my-favorite-color "green")
;; you define functions with lambdas. Functions auto return their last line
(define my-favorites
(lambda (color number)
(string-append "My favorite color is " color " and my favorite number is " number)))
; display will print
(display
(my-favorites my-favorite-color (number->string my-favorite-number)))
; and newline prints a newline
(newline)
This works perfectly when run.
Underneath that, I have a little more:
(define greet
(lambda (name)
(string-append "Hello, " name)))
(display (greet "World"))
When running this file, I can not seem to get "Hello, World"to print. The first display works beautifully, but the second one does not do anything, and I can't explain why. At first I thought this might have something to do with how scheme runs in an interactive environment normally, so I stripped out the first block of code, but still nothing happens.
If I load the file in an interactive session, the "greet" function works perfectly, so I think this must be something odd about the display function.
Can anyone explain why my first display works but my second one does not?
Here is a github link to the exact file
Related
I'm trying to use syntax parameters in order to inject new syntax where I need it to be injected. The result of this is then used in other syntax.
However, it's not working as I expect it to. Here's a minimal working example:
(require racket/stxparam)
(require (for-syntax racket/stxparam))
;; declare parameter to be replaced with code
(define-syntax-parameter placeholder
(lambda (stx)
(raise-syntax-error
(syntax-e stx)
"can only be used inside declare-many-commands")))
;; this is just to print what 'arg' looks like
(define-syntax (print-syntax stx)
(syntax-case stx ()
[(_ arg)
#'(displayln 'arg)]))
;; this is the top-level entity invoked to produce many commands
(define-syntax-rule (declare-many-commands cmds)
(begin
(let ([X 10])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))
(let ([X 20])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))))
(declare-many-commands
(print-syntax placeholder))
What I would like to get as result when running this is:
10
20
but what I get is:
placeholder
placeholder
EDIT:
Posted a new question to refine the problem: Injecting syntax at compile time using Racket's syntax parameters?
The problem here is that your print-syntax macro quotes its input, and inputs to macro transformers are unexpanded syntax. This means that the expansion of (print-syntax placeholder) will always be (displayln 'placeholder), and no macroexpansion ever occurs under quote, so the placeholder binding in scope is irrelevant.
If you want to use the syntax parameter, you need to actually produce a reference to the placeholder binding. In this case, you just need to remove the use of quote. You could change print-syntax to (displayln arg), but at that point, there’s really no reason for print-syntax to be a macro, since it’s equivalent to the displayln function. Just use that instead:
(declare-many-commands
(displayln placeholder))
This will print 10 and 20 as you expect.
It’s possible you really do want the quote, and I don’t understand your question. In that case, though, I think it’s difficult for me to understand what you’re getting at without some additional context.
I am computer science student in university, and my professor give me assignment about Scheme..
then, i set up the scheme 9.2 version, and try to this but, i'm gonna be crazy because of this![enter image description here][1]
52 error> (display "hi")
hi
;Unspecified return value
what is that? ;Unspecified return value
i wanna just display "hi" !
i have questions, how to remove that and how call like that? error code?, check text? or... what? there is a word?
thanks to read....
Your are using the read-eval-print loop. This has the effect that every expression you feed it has a response. If you don't like that you can run the program instead of using the REPL.
How to run a program is not covered by the standard so you need to check the documentation for your chosen implementation.
Here is an example using Ikarus:
#!r6rs
(import (rnrs))
(+ 4 5)
(display "Hello, world!")
(newline)
I've saved it as test.scm and I start it like this:
$ ikarus --r6rs-script test.scm
Hello, world!
$
Notice the result of (+ 4 5) is not displayed. It is dead code since the value is calculated, but then thrown away since it is not used and then continues to evaluate the next expression. Nothing is printed unless you explicit ask it to. In Ikarus REPL you'll see this:
> (+ 4 5)
9
> (display "Hello, world!")
Hello, world!> (newline)
>
It doesn't print the undefiend value #<void>> in the Ikarus REPL. To see it you need to display it:
(display (if #f #t))
; ==> #<void> (not printed by the REPL), but `display` will print `#<void>`
Is it possible to update the program code while it is being interpreted by csi, the Chicken Scheme Interpreter? If so, how?
So that I can interactively change part of the code and immediately see the effects of that changes.
For example, suppose I have written the following program:
(define (loop)
(print "Ciao")
(rest 1)
(loop))
(loop)
(assume (rest 1) has the effect of pausing the program for a second).
If I run this program, trough csi, it prints the string "Ciao" every second. If I change the string "Ciao" into something else, for example into "else", and I save the program code file, then csi continue interpreting the old program code, so I continuously see the string "Ciao". I'd like, in this case, that when I save the modified code with the string "Ciao" replaced by "else", csi continue its interpretation job by looking into the modified file, instead of the old file.
So that I obtain as output some "Ciao" followed by some "else": the "else" start to appear when I replace "Ciao" by "else" in the source code.
In general, the answer is "don't". The way you're supposed to use the REPL is by evaluating piecemeal changes against it, then evaluating a function or two to make sure everything went as expected. Part of this approach is structuring your program so that it can be easily tested in pieces, which implies not automatically starting any infinite loops. In the specific case you're asking about, you could instead write
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
You can now incrementally develop do-stuff, periodically evaluating new versions to your interpreter and calling them to make sure they work, then eventually calling start once you're confident that it's doing the right thing.
You may get mileage out of this similar question asked about Common Lisp.
As an aside, if you were using Common Lisp and SLIME, you could now do more or less what you proposed:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
Starting that up would start printing Ciao on separate lines in your SLIME REPL. If you changed do-stuff to
(defun do-stuff ()
(format t "else~%"))
then hit it with C-c C-c (the default binding for slime-compile-defun), you'd see your SLIME REPL start printing else lines in-flight.
CL-USER> (main-loop)
Ciao
Ciao
Ciao
; compiling (DEFUN DO-STUFF ...)else
else
else
else
else
else
; Evaluation aborted on NIL. User break.
CL-USER>
I'm not sure how to accomplish the same thing in Scheme, but I'm reasonably sure it's possible.
All that being said, you sometimes want to run a program part of which is an infinite loop. A real world example would be while testing a TCP server of some sort. If you're in such a situation, and your desired workflow is
Write file
Run csi my-file.scm
Edit file
Kill csi
Run csi my-file.scm
goto 3
and you basically just want to automate steps 4 through 6, you'll need an external tool to do it for you. Take a look at entr or hsandbox (the latter doesn't have Scheme support out of the box, but it doesn't look like it would be too hard to add).
There is no common way to make a running program check its source for changes but you there seems to be enough feratures available in Chicken to roll your own:
(use posix)
(use srfi-18)
(define (watch-reload! file)
(define (tsleep n)
(thread-sleep! (seconds->time (+ n (time->seconds (current-time))))))
(define (get-time)
(file-modification-time file))
(thread-start!
(lambda ()
(let loop ((filetime '()))
(let ((newtime (get-time)))
(when (not (equal? filetime newtime))
(load file))
(tsleep 10)
(loop newtime))))))
Now all you have to do is to use watch-reload! instead of load and it will check and reload every 10 seconds if the file has been modified.
If you save when the file is not valid scheme it stops working until you call watch-reload! on it again.
It may be that chicken programmers might have a better solution.
Quite often I define a ruby symbol (eg. :some_value), then I want to create a method with the same name def some_value.
Unfortunately, the autocompletion(M + /) for the second occurrence of some_value string does not work, being slightly different (:some_value vs some_value).
How can I setup emacs to handle such events?
Assuming that M-/ is bound to dabbrev-expand, you can configure dabbrev-mode to ignore certain prefixes when expanding strings. To make a single colon a prefix to be ignored, type
M-x customize-group
and then
dabbrev
This will take you to the customization page for dabbrev-mode. Go to the point Dabbrev Abbrev Skip Leading Regexp and click on Value menu. From the menu, pick "Regexp".
Now you see a textfield labeled "Regexp: " next to the value menu in which you enter a single colon.
:
Then click on the button State in the next line and choose the value "Save for Future Sessions".
First, my results! I typed :some_crazy_symbol in my model. On a newline, I typed def so, hit M-/ twice, and ended up with
def some_crazy_symbol
end
(Rinari supplied the end.)
I got this to work quite well by using hippie-expand. If you want to test it out, bind hippie-expand to M-/ like so:
(global-set-key (kbd "M-/") 'hippie-expand)
Heres' the documentation. Hippie expand works by trying out a number of different expansions on the current point. These expansions are stored in the hippie-expand-try-functions-list variable. On my system (and be default), this variable is set to:
(try-complete-file-name-partially try-complete-file-name try-expand-all-abbrevs try-expand-list try-expand-line try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill try-complete-lisp-symbol-partially try-complete-lisp-symbol)
The minibuffer readout showed that this particular expansion was accomplished using the try-expand-dabbrev function.
Not a direct answer to your question, but you should get more intelligent Ruby autocompletion by using auto complete mode paired with rsense.
If Dabbrev Abbrev Skip Leading Regexp and hippie-expand doesn't do exactly what you want and you've got some elisp skills, you could create a custom function for hippie-expand.
See the section about "substring expansion" on the hippie-expand page on the emacs-wiki. There's a function you could use there you could tailor to customize..
Substring Expansion
When doing lisp programming standard dabbrev is less useful, because Emacs has no namespaces, so in a package symbols begin with the same prefix, therefore the same prefix has to be typed again and again if one wants to complete symbols from the package. As with IswitchBuffers it is much more effective if a unique substring can be typed to get to the desired symbol.
Dabbrev offers nothing in this regard, so I turned to Hippie Expand which I had never used before.
Here’s a function based on hippie expand dabbrev expansion which performs substring expansion:
(defun try-my-dabbrev-substring (old)
(let ((old-fun (symbol-function 'he-dabbrev-search)))
(fset 'he-dabbrev-search (symbol-function 'my-dabbrev-substring-search))
(unwind-protect
(try-expand-dabbrev old)
(fset 'he-dabbrev-search old-fun))))
(defun my-dabbrev-substring-search (pattern &optional reverse limit)
(let ((result ())
(regpat (cond ((not hippie-expand-dabbrev-as-symbol)
(concat (regexp-quote pattern) "\\sw+"))
((eq (char-syntax (aref pattern 0)) ?_)
(concat (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+"))
(t
(concat (regexp-quote pattern)
"\\(\\sw\\|\\s_\\)+")))))
(while (and (not result)
(if reverse
(re-search-backward regpat limit t)
(re-search-forward regpat limit t)))
(setq result (buffer-substring-no-properties (save-excursion
(goto-char (match-beginning 0))
(skip-syntax-backward "w_")
(point))
(match-end 0)))
(if (he-string-member result he-tried-table t)
(setq result nil))) ; ignore if bad prefix or already in table
result))
I figured I'd share the solution I came up with that works for hippie-expand.
To summarize:
(defun hippie-expand-ruby-symbols (orig-fun &rest args)
(if (eq major-mode 'ruby-mode)
(let ((table (make-syntax-table ruby-mode-syntax-table)))
(modify-syntax-entry ?: "." table)
(with-syntax-table table (apply orig-fun args)))
(apply orig-fun args)))
(advice-add 'hippie-expand :around #'hippie-expand-ruby-symbols)
hippie-expand will expand symbols in ruby-mode when : is considered a punctuation character, so this advice creates a temporary syntax table where : is a punctuation character and calls hippie-expand with it.
Let's say I need to check if hello.el file is read or not.
(defun hello ()
"Test"
(interactive)
(message "Hello, world"))
(format "hello")
(provide 'smcho)
I used the (format "hello") to show something, but it doesn't seem to work.
How can I know if an elisp module is read.
You should use message instead:
(message "hello")
format simply generates a formatted string, much like if you had
(+ 1 2)
which would result in adding two numbers. Nothing is done with the result, which is why you didn't see it. If you're familiar with C, it's much like having a line
sprintf(s, "hello"); /* this produces no output */
Note: If you have lots of these, you might need to customize the variable message-log-max.