53
Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in Chief of Anarchaia Euruko 2005

Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Dynamic Scope and Context-oriented

ProgrammingChristian Neukirchen

Editor in Chief of Anarchaia

Euruko 2005

Page 2: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Overview

• Dynamic scope

• Context-oriented Programming

• Implementing ContextR

• “Surprise”

Page 3: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Chapter IDynamic Scope

Page 4: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Review:Lexical Scope

def adder(n) v = 0 lambda { v += n }end

add_one = adder 1p add_one.callp add_one.callp add_one.call

# => 1# => 2# => 3

# lexical scope# closure

Page 5: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Comparision

Lexical Scope:

Variables are looked up in the binding they were defined.

Dynamic Scope:

Variables are looked up dynamically, in the current binding (not the defining one).

Page 6: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

x = 2 x = 3

Lexical lookup

def a; x = 1; b; print x; enddef b; x = 2; c; print x; enddef c; x = 3; print x; end

x = 1

# 3 2 1

amain b c

Bindings:

Stack:

Page 7: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Global lookup

def a; $x = 1; b; print $x; enddef b; $x = 2; c; print $x; enddef c; $x = 3; print $x; end

$x = 3

# 3 3 3

amain b c

Page 8: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Dynamic lookup

Dynamic.variable :xdef a Dynamic.let :x => 1 do b Dynamic.let :x => 2 do c end endend

def b Dynamic.let :x => 3 do c end cend

def c print Dynamic[:x]end

# 3 1 2

Page 9: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

:x = 1

:x = 3

Scope diagram

amain

b

c

:x = 2

c

c

Page 10: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Using Dynamic Scope

• Parametrization:

• STDIN, STDOUT (think ERb + puts)

• Passing objects around without explicit mention

• Dissident, my DI container, stores the currently active containers in a dynamic variable

Page 11: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Using dynamic.rbrequire 'dynamic'

Dynamic.variable :eur2usd_factor => 1.3068

def eur2usd(euro) euro * Dynamic.eur2usd_factorend

p eur2usd(10) # => 13.068p eur2usd(0.77) # => 1.006236

Dynamic.let :eur2usd_factor => 0.9267 do p eur2usd(10) # => 9.267 p eur2usd(0.77) # => 0.713559end

p eur2usd(10) # => 13.068

Page 12: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Implementation

• Dynamic variables are stored globally accessible.

• Dynamic.let is roughly: old = Dynamic[variable] Dynamic[variable] = new yield Dynamic[variable] = old

• Using the Ruby stack to keep track of previous definitions

Page 13: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Implementation

• Dynamic variables, not “real” dynamic scope.

• Dynamic scope is easy to implement in C

• Local variable infrastructure can be reused.

‣ Would make a good addition to future Ruby versions. (Now, fight about a sigil!)

Page 14: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Chapter IIContext-oriented

Programming

Page 15: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

The idea

• Imagine you can’t only dynamically scope variables, but also methods.

Page 16: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Layering Methods

• Methods sometimes need to fulfill several concerns:

• Logging

• Data validation

• Database handling (connecting, transactions)

• …

Page 17: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

wrap

• Methods have several “slices”:

• a “core”

• hooks to run before

• hooks to run after

• hooks to wrap the core

• Comparable to AOP

• More are imaginable, but not implemented yet

wrap

Defining layered methods

core

pre

pre

post

post

Page 18: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Ensure database connectionTransaction

Website Example

Debit

Validate input

Check credentials

Log as successful

Redirect user to homepage

Security

Web

Database

Logging

Web

Page 19: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

In ContextR:

class Website layer :security layer :web layer :database layer :logging

def debit; ...; endend

Page 20: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

In ContextR:

class Website security.pre :debit do check_credentials end web.pre :debit do validate_input endend

Page 21: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

In ContextR:class Website database.wrap :debit do |n| connect_to_database n.call_next ensure close_database end database.wrap :debit do |n| transaction { n.call_next } endend

Page 22: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

In ContextR:

class Website logging.post :debit do |n| log "Debit successful: " << n.return_value end web.post :debit do redirect_back_home endend

Page 23: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Configuring the Application

# DevelopmentContextR.with_layers :web, :database, :logging do Website.newend

Page 24: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Configuring the Application

# ProductionContextR.with_layers :web, :database, :security do...

# Unit testingContextR.with_layers :mock_db do...

Page 25: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Comparision to AOP

• Some may know these ideas from “Aspect-oriented Programming”…

• …but Context-oriented Programming is more:

• The program can be reconfigured completely at runtime.

Page 26: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Reconfiguration for testing:

def test_logging ContextR.with_layers :logging do assert_logged ... endend

ContextR.with_layers :mock_db do run_testsend

Page 27: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

More usages

• Layers also can be defined in Modules:

• Mix-in and ducktyping allow for boundless extensibility

• Generic User Interfaces (Naked Objects on steroids)

• …

Page 28: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Chapter IIIImplementing

ContextR

Page 29: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Implementation

• ContextR was written in about four hours this week.

• API inspired by ContextL, written by Pascal Constanza (see references).

• 281 LoC + 171 LoC for dynamic variables.

• Proof-of-Concept, but not ugly.

Page 30: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Implementing compound methods

• Compund methods are implemented using “salami tactics”

• Each method gets split up into lots of smaller methods

• A driver method figures which to call…

• …and what to do with the results.

Page 31: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Rough translation of the Website example

def debit _debit_pre_00001_;_debit_pre_00002_ _debit_wrap_00003_ { _debit_wrap_00004_ { r = _debit_core_00005_ } } _debit_post_00006_;debit_post_00007_ rend

Page 32: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Implementation

• In reality, it does more:

• Check for active layers

• Keep track of arguments and return values

• Allow for premature exits

• Fully dynamic, for now

Page 33: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Limitations

• Most severe limitation in Ruby <1.9

• Blocks can’t take blocks as arguments

• Blocks are used heavily in ContextR

• ContextR can’t pass blocks to slices

• No problem to do in Ruby >=1.9

Page 34: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Performanceof ContextR

• In one word: horrible.

• Method calls are up to 200x slower.

• You can stop laughing now.

• Optimization is possible…

Page 35: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Ideas for optimizing ContextR

• “Compilation” of methods by generating a string that calls the method slices

• Caching generated methods by active contexts

• “Deoptimization”

• Redefining all affected methods on context changes (heavily depends on the way ContextR is used).

Page 36: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Ideas for optimizing ContextR

• Hoping that YARV will be more efficient to enable above techniques in an useful way.

• “It’s just method calls.”

Page 37: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Chapter IV“Surprise, surprise”

Page 38: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Using ContextRto implement…

Page 39: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

NamespaceSelectors

Page 40: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

I live “behind the moon”,what are they?

• First introduced by Matz at RubyConf 2004

• To appear in Ruby 2.0

• Solving an “old” problem of Ruby

• “How can I change Ruby’s core methods without breaking other code?”

Page 41: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

ContextR Namespaces:Declaration

class Array namespace :foo do def mungle zip(reverse).flatten end endend

Page 42: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

ContextR Namespaces:Usage

class Foo namespace :foo

def initialize p [1,2,3].mungle endend

Page 43: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

ContextR Namespaces:Trying…

Foo.new

[1,2,3].mungle rescue p $!

# [1, 3, 2, 2, 3, 1]

# ~> #<NoMethodError: undefined method `mungle' for 123:Array (only in :namespace_foo)>

Page 44: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Implementation ofContextR Namespaces

• Each namespace gets a layer

• namespace(symbol) makes the default layer wrap all methods with appropriate with_layers calls

• using method_added

Page 45: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Implementation of ContextR Namespaces

• namespace(symbol, &block) defines a layer on method_added, activates it, and class_evals the block to automatically claim all the methods defined in the block.

• This probably qualifies as hack. :^)

Page 46: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Summary:

• ~680 LoC written in about six hours total

• Possible to implement ~97% (estimated) of CLOS in pure Ruby

• Lacking const_defined, e.g.

• Not a single use of eval(string)

• Loads of fun

Page 47: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Question::Time === Time.now

Page 48: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

References

•“Language Constructs for Context-oriented Programming–An Overview of ContextL” by Pascal Costanza and Robert Hirschfeld

http://p-cos.net/documents/contextl-overview.pdf

•“Dynamically Scoped Functions as the Essence of AOP” by Pascal Costanza.

http://p-cos.net/documents/dynfun.pdf

•http://chneukirchen.org/blog/archive/2005/04/dynamic-variables-in-ruby.html

Page 49: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Thanks to…

• Mauricio Fernández for telling me I already was half-way done implementing namespaces and helping me polishing the slides.

• #ruby-lang on freenode for help in deepest metaprogramming dungeons.

• You, following this talk until the end.

Page 50: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

On the web:

http://chneukirchen.org/talks/euruko-2005

Page 51: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Outtakes:

Page 52: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

History ofDynamic Scope

• Used by default in old Lisps

• Lisp 1.5

• MacLisp

• Emacs Lisp

• Still provided and used by modern Lisps

• “special variables” (defvar)

Page 53: Dynamic Scope and Context-oriented Programming › talks › euruko-2005 › chneukirchen-euruk… · Dynamic Scope and Context-oriented Programming Christian Neukirchen Editor in

Analysis:x = 1

amain

b

c

Stack:

:x = 2

:x = 3

c

c