summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrant Shangreaux <grant@unabridgedsoftware.com>2022-07-12 16:34:53 -0500
committerGrant Shangreaux <grant@unabridgedsoftware.com>2022-07-12 16:34:53 -0500
commit79dd7f85720d2402634304530d446f24b920839d (patch)
tree8c5253ffd2d8f3c81351f8d6fe6ad579afb44f37
Add: scopes-and-bindings talkmaster
-rwxr-xr-xscopes/#foo.rb#3
-rwxr-xr-xscopes/bindings-and-scopes.org214
-rwxr-xr-xscopes/lspace.rb21
3 files changed, 238 insertions, 0 deletions
diff --git a/scopes/#foo.rb# b/scopes/#foo.rb#
new file mode 100755
index 0000000..92d1b69
--- /dev/null
+++ b/scopes/#foo.rb#
@@ -0,0 +1,3 @@
+def goo(x)
+
+end \ No newline at end of file
diff --git a/scopes/bindings-and-scopes.org b/scopes/bindings-and-scopes.org
new file mode 100755
index 0000000..b1b5633
--- /dev/null
+++ b/scopes/bindings-and-scopes.org
@@ -0,0 +1,214 @@
+#+TITLE: Bindings and Scopes
+#+AUTHOR: Grant Shangreaux
+
+* Definitions
+** What is a "Binding"?
+
+ - 𝑓(x) = x²; x = 10 ⟵ "binding" the value 10 to x (sort of)
+ - an identifier that acts as a reference to some place in memory
+ that can be "bound" to a specific value. entity, object, etc.
+
+ #+begin_src ruby
+ x = 5 # binding the variable name x to the value 5
+
+ def square(x)
+ x * x
+ end
+
+ # here the argument 10 binds to the x variable in the method body
+ square(10)
+ #+end_src
+
+** /Scope/ of Variable Bindings
+
+ *Scope* refers to /where/ in the source code an identifer can
+ be accessed. Where is something visible?
+
+ *Lexical Scope* is the textual scope defined in the source code
+
+ *Indefinite Scope* a reference can be used anywhere in the
+ program. the value of the reference is determined at runtime
+
+** /Extent/ of Variable Bindings
+
+ *Extent* refers to /when/, as the program is executing,
+ the binding exists.
+
+ *Indefinite Extent* binding persists as long as a possibility
+ of reference remains. GC and Closures
+
+ *Dynamic Extent* binding is established and disestablished
+ explicitly. Stack-like nested runtime constructs
+
+** Types of Bindings
+
+ *Lexical bindings* have /lexical scope/ and /indefinite extent/
+
+ *Dynamic bindings* have /indefinite scope/ and /dynamic extent/
+
+* Ruby
+
+Ruby, like most modern languages, uses /lexical binding/.
+Each new textual part of source code creates a new lexical scope.
+~Kernel.binding~ will return the ~Binding~ object of the current scope
+
+** Scope Gates
+
+ A new scope is entered any time you:
+ - define a class with ~class SomeClass~
+ - define a module with ~module SomeModule~
+ - define a method with ~def some_method~
+
+ Old scope is no longer available
+
+** Scope Gate Example
+
+#+begin_src ruby :results output
+v0 = 0
+class SomeClass # Scope gate
+ v1 = 1
+ p local_variables # As the name says, it gives you all local variables in scope
+
+ def some_method # Scope gate
+ v2 = 2
+ p local_variables
+ end # end of def scope gate
+end # end of class scope gate
+
+some_class = SomeClass.new
+some_class.some_method
+#+end_src
+
+#+RESULTS:
+: [:v1]
+: [:v2]
+
+** Breaking Scope Gates!
+
+ - define a class using ~Class.new~
+ - define a module using ~Module.new~
+ - define a method with ~define_method~
+
+** Breaking Scope Gate Example
+
+#+begin_src ruby :results output
+v0 = 0
+SomeClass = Class.new do
+ v1 = 1
+ p local_variables
+
+ define_method(:some_method) do
+ v2 = 2
+ p local_variables
+ end
+end
+
+some_class = SomeClass.new
+some_class.some_method
+#+end_src
+
+#+RESULTS:
+: [:v1, :v0, :some_class]
+: [:v2, :v1, :v0, :some_class]
+
+** Closures
+
+#+begin_src ruby :results output
+ i = 0
+
+ counter = lambda do
+ puts i
+ i += 1
+ end
+ i = 10
+ 3.times { counter.call }
+#+end_src
+
+#+RESULTS:
+: 10
+: 11
+: 12
+
+** Quiz
+
+#+begin_src ruby
+ class SomeClass
+ b = 'hello'
+ @@m = 'hi'
+
+ def initialize
+ @some_var = 1
+ c = 'hi'
+ end
+
+ def some_method
+ # what bindings are available here?
+ a = 'hello'
+ end
+ end
+
+ some_object = SomeClass.new
+ some_object.some_method
+#+end_src
+
+* Emacs Lisp
+
+Until recently, everything was dynamically scoped.
+
+New code is adopting lexical binding as much as possible.
+
+Dynamic Scope is *powerful* and enhances extensibility.
+
+** Special Variables
+
+#+begin_src emacs-lisp :results output
+ (defvar *special* 'i-am-special)
+
+ (defun print-special ()
+ (print *special*))
+
+ (let ((*special* 'lookee-here))
+ (print-special))
+
+ (print-special)
+#+end_src
+
+** Lexical Binding
+
+#+begin_src emacs-lisp :results output
+ (setq normal 'i-am-normal)
+
+ (defun print-normal ()
+ (print normal))
+
+ (let ((normal 'does-this-work?))
+ (print-normal))
+
+ (print-normal)
+#+end_src
+
+** symbol-value
+
+(symbol-value SYMBOL)
+
+ This function does not change global state, including the match data.
+
+Return SYMBOL’s value. Error if that is void.
+Note that if ‘lexical-binding’ is in effect, this returns the
+global value outside of any lexical scope.
+
+** lexical-binding
+
+ Automatically becomes buffer-local when set.
+ This variable is safe as a file local variable if its value
+ satisfies the predicate ‘booleanp’.
+ Probably introduced at or before Emacs version 24.1.
+
+Documentation:
+Whether to use lexical binding when evaluating code.
+Non-nil means that the code in the current buffer should be evaluated
+with lexical binding.
+This variable is automatically set from the file variables of an
+interpreted Lisp file read using ‘load’. Unlike other file local
+variables, this must be set in the first line of a file.
+
diff --git a/scopes/lspace.rb b/scopes/lspace.rb
new file mode 100755
index 0000000..cf027e1
--- /dev/null
+++ b/scopes/lspace.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'lspace'
+
+def log(str)
+ puts "#{LSpace[:log_prefix]}: #{str}"
+end
+
+def handle_request(req)
+ LSpace.with(log_prefix: "handling request") do
+ log Time.now
+ log req[:status]
+ log req[:body]
+ end
+
+ Lspace.with(log_prefix: "app") do
+ log "request handled"
+ end
+end
+
+handle_request({status: 200, body: "success!"})