summaryrefslogtreecommitdiff
path: root/scopes/bindings-and-scopes.org
blob: b1b5633d0ae226333203b16b1b278acbf62b9c55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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.