about summary refs log blame commit diff stats
path: root/js/games/nluqo.github.io/~bh/downloads/simply/functions.scm
blob: e421ee3b043cd1c07e8f5f9fc504857b20c02e75 (plain) (tree)



















































































































































































































































                                                                       
;;; The functions program

(define (functions)
  (read-line)
  (show "Welcome to the FUNCTIONS program.")
  (functions-loop))

(define (functions-loop)
  (let ((fn-name (get-fn)))
    (if (equal? fn-name 'exit)
	"Thanks for using FUNCTIONS!"
	(let ((args (get-args (arg-count fn-name))))
	  (if (not (in-domain? args fn-name))
	     (show "Argument(s) not in domain.")
	     (show-answer (apply (scheme-function fn-name) args)))
	  (functions-loop)))))

(define (get-fn)
  (display "Function: ")
  (let ((line (read-line)))
    (cond ((empty? line)
	   (show "Please type a function!")
	   (get-fn))
	  ((not (= (count line) 1))
	   (show "You typed more than one thing!  Try again.")
	   (get-fn))
	  ((not (valid-fn-name? (first line)))
	   (show "Sorry, that's not a function.")
	   (get-fn))
	  (else (first line)))))

(define (get-args n)
  (if (= n 0)
      '()
      (let ((first (get-arg)))
	(cons first (get-args (- n 1))))))

(define (get-arg)
  (display "Argument: ")
  (let ((line (read-line)))
    (cond ((empty? line)
	   (show "Please type an argument!")
	   (get-arg))
	  ((and (equal? "(" (first (first line)))
		(equal? ")" (last (last line))))
	   (let ((sent (remove-first-paren (remove-last-paren line))))
	     (if (any-parens? sent)
		 (begin
		  (show "Sentences can't have parentheses inside.")
		  (get-arg))
		 (map booleanize sent))))
	  ((any-parens? line)
	   (show "Bad parentheses")
	   (get-arg))
	  ((empty? (bf line)) (booleanize (first line)))
	  ((member? (first (first line)) "\"'")
	   (show "No quoting arguments in this program.  Try again.")
	   (get-arg))
	  (else (show "You typed more than one argument!  Try again.")
		(get-arg)))))

(define (any-parens? line)
  (let ((letters (accumulate word line)))
    (or (member? "(" letters)
	(member? ")" letters))))

(define (remove-first-paren line)
  (if (equal? (first line) "(")
      (bf line)
      (se (bf (first line)) (bf line))))

(define (remove-last-paren line)
  (if (equal? (last line) ")")
      (bl line)
      (se (bl line) (bl (last line)))))

(define (booleanize x)
  (cond ((equal? x "#t") #t)
	((equal? x "#f") #f)
	(else x)))

(define (show-answer answer)
  (newline)
  (display "The result is: ")
  (if (not answer)
      (show "#F")
      (show answer))
  (newline))

(define (scheme-function fn-name)
  (cadr (assoc fn-name *the-functions*)))

(define (arg-count fn-name)
  (caddr (assoc fn-name *the-functions*)))

(define (type-predicate fn-name)
  (cadddr (assoc fn-name *the-functions*)))

(define (in-domain? args fn-name)
  (apply (type-predicate fn-name) args))


;; Type predicates

(define (word-or-sent? x)
  (or (word? x) (sentence? x)))

(define (not-empty? x)
  (and (word-or-sent? x) (not (empty? x))))

(define (two-numbers? x y)
  (and (number? x) (number? y)))

(define (two-reals? x y)
  (and (real? x) (real? y)))

(define (two-integers? x y)
  (and (integer? x) (integer? y)))

(define (can-divide? x y)
  (and (number? x) (number? y) (not (= y 0))))

(define (dividable-integers? x y)
  (and (two-integers? x y) (not (= y 0))))

(define (trig-range? x)
  (and (number? x) (<= (abs x) 1)))

(define (hof-types-ok? fn-name stuff range-predicate)
  (and (valid-fn-name? fn-name)
       (= 1 (arg-count fn-name))
       (word-or-sent? stuff)
       (empty? (keep (lambda (element)
		       (not ((type-predicate fn-name) element)))
		     stuff))
       (null? (filter (lambda (element)
			(not (range-predicate element)))
		      (map (scheme-function fn-name)
			   (every (lambda (x) x) stuff))))))

(define (member-types-ok? small big)
  (and (word? small)
       (or (sentence? big) (= (count small) 1))))


;; Names of functions as functions

(define (named-every fn-name list)
  (every (scheme-function fn-name) list))

(define (named-keep fn-name list)
  (keep (scheme-function fn-name) list))

(define (valid-fn-name? name)
  (assoc name *the-functions*))


;; The list itself
          
(define *the-functions*
  (list (list '* * 2 two-numbers?)
	(list '+ + 2 two-numbers?)
	(list '- - 2 two-numbers?)
	(list '/ / 2 can-divide?)
	(list '< < 2 two-reals?)
	(list '<= <= 2 two-reals?)
	(list '= = 2 two-numbers?)
	(list '> > 2 two-reals?)
	(list '>= >= 2 two-reals?)
	(list 'abs abs 1 real?)

	(list 'acos acos 1 trig-range?)
	(list 'and (lambda (x y) (and x y)) 2 
	      (lambda (x y) (and (boolean? x) (boolean? y))))
	(list 'appearances appearances 2 member-types-ok?)
	(list 'asin asin 1 trig-range?)
	(list 'atan atan 1 number?)
	(list 'bf bf 1 not-empty?)
	(list 'bl bl 1 not-empty?)
	(list 'butfirst butfirst 1 not-empty?)
	(list 'butlast butlast 1 not-empty?)
	(list 'ceiling ceiling 1 real?)
	(list 'cos cos 1 number?)
	(list 'count count 1 word-or-sent?)
	(list 'equal? equal? 2 (lambda (x y) #t))
	(list 'even? even? 1 integer?)
	(list 'every named-every 2
	      (lambda (fn stuff)
		(hof-types-ok? fn stuff word-or-sent?)))
	(list 'exit '() 0 '())
	   ; in case user applies number-of-arguments to exit
	(list 'exp exp 1 number?)
	(list 'expt expt 2
	      (lambda (x y)
		(and (number? x) (number? y)
		     (or (not (real? x)) (>= x 0) (integer? y)))))
	(list 'first first 1 not-empty?)
	(list 'floor floor 1 real?)
	(list 'gcd gcd 2 two-integers?)
	(list 'if (lambda (pred yes no) (if pred yes no)) 3
	      (lambda (pred yes no) (boolean? pred)))
	(list 'item item 2
	      (lambda (n stuff)
		(and (integer? n) (> n 0)
		     (word-or-sent? stuff) (<= n (count stuff)))))
	(list 'keep named-keep 2
	      (lambda (fn stuff)
		(hof-types-ok? fn stuff boolean?)))
	(list 'last last 1 not-empty?)
	(list 'lcm lcm 2 two-integers?)
	(list 'log log 1 (lambda (x) (and (number? x) (not (= x 0)))))
	(list 'max max 2 two-reals?)
	(list 'member? member? 2 member-types-ok?)
	(list 'min min 2 two-reals?)
	(list 'modulo modulo 2 dividable-integers?)
	(list 'not not 1 boolean?)

	(list 'number-of-arguments arg-count 1 valid-fn-name?)
	(list 'odd? odd? 1 integer?)
	(list 'or (lambda (x y) (or x y)) 2
	      (lambda (x y) (and (boolean? x) (boolean? y))))
	(list 'quotient quotient 2 dividable-integers?)
	(list 'random random 1 (lambda (x) (and (integer? x) (> x 0))))
	(list 'remainder remainder 2 dividable-integers?)
	(list 'round round 1 real?)
	(list 'se se 2
	      (lambda (x y) (and (word-or-sent? x) (word-or-sent? y))))
	(list 'sentence sentence 2
	      (lambda (x y) (and (word-or-sent? x) (word-or-sent? y))))
	(list 'sentence? sentence? 1 (lambda (x) #t))
	(list 'sin sin 1 number?)
	(list 'sqrt sqrt 1 (lambda (x) (and (real? x) (>= x 0))))
	(list 'tan tan 1 number?)
	(list 'truncate truncate 1 real?)
	(list 'vowel?
	      (lambda (x)
		(and (word? x)
		     (= (count x) 1)
		     (member? x '(a e i o u))))
	      1
	      (lambda (x) #t))
	(list 'word word 2 (lambda (x y) (and (word? x) (word? y))))
	(list 'word? word? 1 (lambda (x) #t))))
= order self.search_forward = forward # -------------------------- # -- Tags # -------------------------- # Tags are saved in ~/.ranger/tagged and simply mark if a # file is important to you in any context. def tag_toggle(self, movedown=None): try: toggle = self.tags.toggle except AttributeError: return sel = self.env.get_selection() toggle(*tuple(map(lambda x: x.realpath, sel))) if movedown is None: movedown = len(sel) == 1 if movedown: self.move(down=1) if hasattr(self.ui, 'redraw_main_column'): self.ui.redraw_main_column() def tag_remove(self, movedown=None): try: remove = self.tags.remove except AttributeError: return sel = self.env.get_selection() remove(*tuple(map(lambda x: x.realpath, sel))) if movedown is None: movedown = len(sel) == 1 if movedown: self.move(down=1) if hasattr(self.ui, 'redraw_main_column'): self.ui.redraw_main_column() # -------------------------- # -- Bookmarks # -------------------------- # Using ranger.container.bookmarks. def enter_bookmark(self, key): """Enter the bookmark with the name <key>""" try: destination = self.bookmarks[key] cwd = self.env.cwd if destination.path != cwd.path: self.bookmarks.enter(key) self.bookmarks.remember(cwd) except KeyError: pass def set_bookmark(self, key): """Set the bookmark with the name <key> to the current directory""" self.bookmarks[key] = self.env.cwd def unset_bookmark(self, key): """Delete the bookmark with the name <key>""" self.bookmarks.delete(key) def draw_bookmarks(self): self.ui.browser.draw_bookmarks = True def hide_bookmarks(self): self.ui.browser.draw_bookmarks = False # -------------------------- # -- Pager # -------------------------- # These commands open the built-in pager and set specific sources. def display_command_help(self, console_widget): if not hasattr(self.ui, 'open_pager'): return try: command = console_widget._get_cmd_class() except: self.notify("Feature not available!", bad=True) return if not command: self.notify("Command not found!", bad=True) return if not command.__doc__: self.notify("Command has no docstring. Try using python without -OO", bad=True) return pager = self.ui.open_pager() lines = cleandoc(command.__doc__).split('\n') pager.set_source(lines) def display_help(self, topic='index', narg=None): if not hasattr(self.ui, 'open_pager'): return from ranger.help import get_help, get_help_by_index if narg is not None: help_text = get_help_by_index(narg) else: help_text = get_help(topic) pager = self.ui.open_pager() pager.markup = 'help' lines = help_text.split('\n') pager.set_source(lines) def display_log(self): if not hasattr(self.ui, 'open_pager'): return pager = self.ui.open_pager() if self.log: pager.set_source(["Message Log:"] + list(self.log)) else: pager.set_source(["Message Log:", "No messages!"]) def display_file(self): if not hasattr(self.ui, 'open_embedded_pager'): return try: f = open(self.env.cf.path, 'r') except: pass else: pager = self.ui.open_embedded_pager() pager.set_source(f) # -------------------------- # -- Tabs # -------------------------- # This implementation of tabs is very simple and keeps track of # directory paths only. def tab_open(self, name, path=None): do_emit_signal = name != self.current_tab self.current_tab = name if path or (name in self.tabs): self.enter_dir(path or self.tabs[name]) else: self._update_current_tab() if do_emit_signal: self.signal_emit('tab.change') def tab_close(self, name=None): if name is None: name = self.current_tab if name == self.current_tab: direction = -1 if name == self._get_tab_list()[-1] else 1 previous = self.current_tab self.tab_move(direction) if previous == self.current_tab: return # can't close last tab if name in self.tabs: del self.tabs[name] def tab_move(self, offset): assert isinstance(offset, int) tablist = self._get_tab_list() current_index = tablist.index(self.current_tab) newtab = tablist[(current_index + offset) % len(tablist)] if newtab != self.current_tab: self.tab_open(newtab) def tab_new(self): for i in range(1, 10): if not i in self.tabs: self.tab_open(i) break def _get_tab_list(self): assert len(self.tabs) > 0, "There must be >=1 tabs at all times" return sorted(self.tabs) def _update_current_tab(self): self.tabs[self.current_tab] = self.env.cwd.path # -------------------------- # -- File System Operations # -------------------------- def uncut(self): self.env.copy = set() self.env.cut = False self.ui.browser.main_column.request_redraw() def copy(self, narg=None, dirarg=None): """Copy the selected items""" cwd = self.env.cwd if not narg and not dirarg: selected = (f for f in self.env.get_selection() if f in cwd.files) self.env.copy = set(selected) else: direction = Direction(dirarg or {}) offset = 0 if not direction.vertical(): direction = Direction(down=1) offset = -1 pos, selected = direction.select( override=narg, lst=cwd.files, current=cwd.pointer, pagesize=self.env.termsize[0], offset=offset) self.env.copy = set(selected) self.env.cwd.pointer = pos self.env.cwd.correct_pointer() self.env.cut = False self.ui.browser.main_column.request_redraw() def cut(self, narg=None, dirarg=None): self.copy(narg=narg, dirarg=dirarg) self.env.cut = True self.ui.browser.main_column.request_redraw() def paste_symlink(self): from os import symlink, getcwd from os.path import join copied_files = self.env.copy if not copied_files: return for f in copied_files: try: symlink(f.path, join(getcwd(), f.basename)) except Exception as x: self.notify(x) def paste(self, overwrite=False): """Paste the selected items into the current directory""" from os.path import join, isdir from ranger.ext import shutil_generatorized as shutil_g from ranger.fsobject.loader import LoadableObject copied_files = tuple(self.env.copy) if not copied_files: return original_path = self.env.cwd.path try: one_file = copied_files[0] except: one_file = None if self.env.cut: self.env.copy.clear() self.env.cut = False if len(copied_files) == 1: descr = "moving: " + one_file.path else: descr = "moving files from: " + one_file.dirname def generate(): for f in copied_files: for _ in shutil_g.move(src=f.path, dst=original_path, overwrite=overwrite): yield cwd = self.env.get_directory(original_path) cwd.load_content() else: if len(copied_files) == 1: descr = "copying: " + one_file.path else: descr = "copying files from: " + one_file.dirname def generate(): for f in self.env.copy: if isdir(f.path): for _ in shutil_g.copytree(src=f.path, dst=join(self.env.cwd.path, f.basename), symlinks=True, overwrite=overwrite): yield else: for _ in shutil_g.copy2(f.path, original_path, symlinks=True, overwrite=overwrite): yield cwd = self.env.get_directory(original_path) cwd.load_content() self.loader.add(LoadableObject(generate(), descr)) def delete(self): self.notify("Deleting!", duration=1) selected = self.env.get_selection() self.env.copy -= set(selected) if selected: for f in selected: if os.path.isdir(f.path) and not os.path.islink(f.path): try: shutil.rmtree(f.path) except OSError as err: self.notify(err) else: try: os.remove(f.path) except OSError as err: self.notify(err) self.env.ensure_correct_pointer() def mkdir(self, name): try: os.mkdir(os.path.join(self.env.cwd.path, name)) except OSError as err: self.notify(err) def rename(self, src, dest): if hasattr(src, 'path'): src = src.path try: os.rename(src, dest) except OSError as err: self.notify(err)