Everything is Permitted: Extending Built-ins
-
Upload
andrew-dupont -
Category
Technology
-
view
5.065 -
download
2
description
Transcript of Everything is Permitted: Extending Built-ins
![Page 1: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/1.jpg)
Everything is Permitted:Extending Built-ins
Andrew Duponthttp://andrewdupont.net
![Page 2: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/2.jpg)
Remy Sharp (flickr.com/photos/remysharp)
![Page 3: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/3.jpg)
There’s a whole lot of know-nothing advocacy that’s still happening in the JS/webdev/design world these days, and it annoys me to no end. I’m not sure how our community got so religious and fact-disoriented, but it has got to stop.”
“
Alex Russell
![Page 4: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/4.jpg)
“If you use this book as a guide, by all means leave the road when you wish. That is precisely the use of a road: to reach individually chosen points of departure. By all means break the rules, and break them beautifully, deliberately and well. That is one of the ends for which they exist.”
Robert Bringhurst,The Elements of Typographic Style
![Page 5: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/5.jpg)
George Orwell,“Politics and the English Language”
“Break any of these rules sooner than say anything outright barbarous.”
![Page 6: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/6.jpg)
“Commandments”are no way to write code.
![Page 7: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/7.jpg)
Alex (flickr.com/photos/littlebirdfeet/)
![Page 8: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/8.jpg)
Fuck what you heard, SHORTS ARE DOPE. Just wear them right. Not mid leg like you’re at a fuckin Creed concert.
Donald Glover@DonaldGlover
Echofon30 Jul via
![Page 9: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/9.jpg)
Code has social customs.
![Page 10: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/10.jpg)
IN THE BEGINNING(ca. 2005)
![Page 11: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/11.jpg)
Prototype 1.1
![Page 12: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/12.jpg)
Object.prototype.extend = function(object) { for (var property in object) { this[property] = object[property]; } return this;};
![Page 13: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/13.jpg)
var whiteHouse = { washington: 'adams' };whiteHouse.extend({ adams: 'jefferson' });
for (var president in whiteHouse) console.log(president);//=> washington, adams, extend
![Page 14: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/14.jpg)
![Page 15: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/15.jpg)
http://erik.eae.net/archives/2005/06/06/22.13.54/Object.prototype is verboten
![Page 16: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/16.jpg)
![Page 17: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/17.jpg)
![Page 18: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/18.jpg)
You can do anything you want,assuming it’s all your code
![Page 19: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/19.jpg)
Object.prototype.extendbecame
Object.extend
![Page 20: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/20.jpg)
if (!Array.prototype.push) { Array.prototype.push = function() { var startLength = this.length; for (var i = 0; i < arguments.length; i++) this[startLength + i] = arguments[i]; return this.length; };}
![Page 21: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/21.jpg)
Prototype 1.4 introducedEnumerable
![Page 22: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/22.jpg)
for...in loops on arraysare usually dumb
![Page 23: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/23.jpg)
http://is.gd/js_considered_harmfulJavaScript “Associative Arrays” Considered Harmful
![Page 24: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/24.jpg)
Prototype 1.5 introduced“Extended” elements
![Page 25: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/25.jpg)
// Prototype 1.4Element.addClassName('some_element', 'active');Element.show();$('some_element').setAttribute('title', 'Active item');
// Prototype 1.5$('some_element').addClassName('active').show(). setAttribute('title', 'Active item');
![Page 26: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/26.jpg)
This was slow in IE
![Page 27: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/27.jpg)
Also `typeof document.querySelectorAll('*').item` is 'string' in IE8. Well, that's just silly.
kangax@kangax
16 Dec 08 via web
![Page 28: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/28.jpg)
What’s wrong with extending the DOMhttp://perfectionkills.com/whats-wrong-with-extending-the-dom/
![Page 29: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/29.jpg)
http://is.gd/zakas_maintainable_javascriptMaintainable JavaScript: Don’t modify objects you don’t own
![Page 30: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/30.jpg)
Who owns built-ins?
![Page 31: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/31.jpg)
We all do.
![Page 32: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/32.jpg)
Social customs are a proven wayto manage shared property.
![Page 33: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/33.jpg)
Case in point:RUBY
![Page 34: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/34.jpg)
Ruby and JavaScriptare Smalltalk-influenced
![Page 35: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/35.jpg)
Rails gave RubyActive Support
![Page 36: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/36.jpg)
ActiveSupport::CoreExtensions::Numeric
1.day.ago#=> Thu Apr 21 01:57:24 -0500 2011
(4.years + 12.days).from_now#=> Mon May 04 01:58:30 -0500 2015
7.5.megabytes#=> 7864320.0
![Page 37: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/37.jpg)
result = names.map {|name| name.upcase }# becomes...result = names.map(&:upcase)
Symbol#to_proc
![Page 38: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/38.jpg)
http://brockman.se/2004/method-references/
![Page 39: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/39.jpg)
![Page 40: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/40.jpg)
![Page 41: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/41.jpg)
Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); };};
Prototype 1.4
![Page 42: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/42.jpg)
EcmaScript 5.1 Specification
![Page 43: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/43.jpg)
Obviously,there were fights along the way
![Page 44: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/44.jpg)
Zed Shaw,“The Chainsaw Infanticide Logger Manuever”
“I only re-open a class after I’ve tried every other option like subclassing, wrapping, etc. If nothing else works or is too much effort for the modification, then I document the hell out of my modification and try desperately to localize the change so that it doesn't hurt anyone else.”
http://is.gd/chainsaw_infanticide
![Page 45: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/45.jpg)
The Higgs Bozo
“Don't slip a concrete dildo into someone's box of Fruit Loops. They won't be happy with your Morning Breakfast Surprise. Put the concrete dildo in a clearly labeled box, with instructions. Then when someone encounters a problem (‘Hey, something is screwing me here. Maybe it's the concrete dildo?’) at least they know to ask.”
http://is.gd/concrete_dildo
![Page 46: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/46.jpg)
Yehuda Katz
“In my mind, in Ruby < 2.0, there’s a category of library which is ‘provide a number of useful core extensions.’ The three major ones are ActiveSupport, Extlib and Facets. In general, applications need to choose one, but not more of these libraries to avoid conflicts.”
http://is.gd/cQar9O
![Page 47: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/47.jpg)
Lessons learned by Rubyists:
![Page 48: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/48.jpg)
Make it obvious when you’re defining core extensions.
module SomeLibrary module CoreExtensions module Object def foo # ... end end end end
class Object include SomeLibrary::CoreExtensions::Objectend
![Page 49: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/49.jpg)
Make core extensions as atomic as possible.
require 'active_support/core_ext/numeric/bytes'
3.megabytes#=> 3145728
3.days.ago# NoMethodError: undefined method `days' for 3:Fixnum
![Page 50: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/50.jpg)
If you must monkey-patch, do so seamlessly.Don’t break the old method’s contract.
class Array alias_method :foo_original :foo def foo(arg) puts "Adding advice to the 'foo' method" foo_original(arg) endend
![Page 51: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/51.jpg)
Unsolved problems:
![Page 52: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/52.jpg)
Only one library gets the privilegeto extend built-ins.
![Page 53: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/53.jpg)
{}.blank?# NoMethodError: undefined method `blank?' for {}:Hash
require 'rails'{}.blank?#=> true
Libraries I require will o"en decide for themselveswhich core extensions will be used.
![Page 54: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/54.jpg)
Can we extend built-inssafely right now?
![Page 55: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/55.jpg)
Object.prototype.extend = function(object) { for (var property in object) { this[property] = object[property]; } return this;};
![Page 56: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/56.jpg)
Object.prototype.extend = function(object) { for (var property in object) { this[property] = object[property]; } return this;};
![Page 57: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/57.jpg)
Object.defineProperty(Object.prototype, 'extend', { writable: true, configurable: true, enumerable: false, value: function() { for (var i = 0, len = arguments.length, source; i < len; i++) { source = arguments[i]; for (var property in source) { if (source.hasOwnProperty(property)) this[property] = source[property]; } } } });
ES5 to the rescue?
![Page 58: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/58.jpg)
var whiteHouse = { washington: 'adams' };whiteHouse.extend({ adams: 'jefferson' });
for (var president in whiteHouse) console.log(president);//=> washington, adams
![Page 59: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/59.jpg)
![Page 60: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/60.jpg)
But wait…
var whiteHouse = { extend: 'adams' };whiteHouse.extend({ adams: 'jefferson' });
// TypeError: Property 'extend' of object #<Object>// is not a function
![Page 61: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/61.jpg)
![Page 62: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/62.jpg)
console.log(extend);//=> [Function]
And also…
![Page 63: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/63.jpg)
![Page 64: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/64.jpg)
Object.prototype is still verboten
![Page 65: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/65.jpg)
If you extend other built-ins,consider turning off enumerability.
![Page 66: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/66.jpg)
What about Node?
![Page 67: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/67.jpg)
node-timehttps://github.com/TooTallNate/node-time
![Page 68: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/68.jpg)
var time = require('time');
var date = new Date();date.setTimeZone('America/Chicago');
console.log(date.toString());console.log(date.getTimezone());console.log(date.getTimezoneAbbr());
Tue Apr 26 2011 02:45:21 GMT-0500 (CDT)America/ChicagoCDT
Output:
![Page 69: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/69.jpg)
What about the browser?
![Page 70: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/70.jpg)
We’ll be needing ES5 polyfills
“A polyfill … is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively.”
Remy Sharphttp://remysharp.com/2010/10/08/what-is-a-polyfill/
![Page 71: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/71.jpg)
if (!Object.keys) { Object.keys = function(object) { if (object !== Object(object)) throw new TypeError('Object.keys called on non-object'); var results = []; for (var property in object) { if (object.hasOwnProperty(property)) results.push(property); }
return results; };}
![Page 72: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/72.jpg)
if (!Function.prototype.bind) { Function.prototype.bind = function(object) { var slice = Array.prototype.slice, args = slice.call(arguments, 1), self = this;
var nop = function() {}; var bound = function() { return self.apply( this instanceof nop ? this : (object || {}), args.concat(slice.call(arguments)) ); }; nop.prototype = self.prototype; bound.prototype = new nop(); return bound; };}
![Page 73: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/73.jpg)
Let’s start with bind.
![Page 74: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/74.jpg)
will have spec compliancefor all methods defined by ES5.
Prototype 1.7.1
![Page 75: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/75.jpg)
Will we be able toextend built-ins safely someday?
![Page 76: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/76.jpg)
The future:
CLASSBOXES
![Page 77: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/77.jpg)
So"ware Composition Group,University of Bern
“[W]e present classboxes, a module system for object-oriented languages that allows method addition and replacement. Moreover, the changes made by a classbox are only visible to that classbox (or classboxes that import it), a feature we call local rebinding.”
http://scg.unibe.ch/research/classboxes
![Page 78: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/78.jpg)
A classbox-like system called “refinements”has been proposed for Ruby 2.0.
module TimeExtensions refine Numeric do def minutes; self * 60; end endend
2.minutes #=> NoMethodError
using TimeExtensions2.minutes #=> 120
![Page 79: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/79.jpg)
Could we have classboxesin JavaScript?
![Page 80: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/80.jpg)
Strawman: Scoped Object Extensions
module NumericExtensions { export extension Time = Number.prototype { days: function() {}, /* ... */
ago: function() {}, fromNow: function() {} }}
function setExpiringCookie(key, value) { import NumericExtensions.Time; var expires = (3).days().fromNow(); setCookie(key, value, expires);}
(3).days().fromNow();//=> TypeError: Object 3 has no method 'days'
![Page 81: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/81.jpg)
SOMEDAY
![Page 82: Everything is Permitted: Extending Built-ins](https://reader038.fdocuments.net/reader038/viewer/2022110303/54b79eea4a79590e758b45ed/html5/thumbnails/82.jpg)
Questions?