--------------040404080407000006030407 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Curt Hibbs wrote: > James Britt wrote: >>Simon Strandgaard wrote: >>>Ruby allows to you enhance the builtin string class with you >> >>own methods, >> >>>which you can invoke "im a string".own_method >>> >>>Thats the sentence I use most. >>>I don't know if there are other languages that allow for this? >> >>JavaScript. >> >>Really. >> >>"JavaScript: It's sweeter than you think." > Yes, JavaScript is underrated. A lot of the things we do with Ruby can be > done with JavaScript (its just not as clean). See attachment. ;) Regards, Florian Gross --------------040404080407000006030407 Content-Type: text/plain; name uby.js" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename uby.js" Object.prototype.clone unction(deepClone) { var result ew this.constructor() for (var property in this) { if (deepClone && typeof(this[property]) 'object') { result[property] his[property].clone(deepClone) } else { result[property] his[property] } } return(result) } Object.prototype.extend unction(other) { if (!this.mixins) this.mixins ] this.mixins.push(other) for (var property in other) if (!this.hasOwnProperty(property)) this[property] ther[property] } Object.prototype.cmp unction(other) { if (this < other) return(-1) if (this > other) return(+1) return(0) } Object.prototype.valuesAt unction() { var obj his return(arguments.toArray().map(function(index) { return(obj[index]) })) } Object.prototype.toArray unction() { if (!this.length) throw("Can't convert") var result ] for (var i ; i < this.length; i++) result.push(this[i]) return(result) } Object.prototype.hash unction() { return(this.toSource().hash()) } Object.prototype.instanceOf unction(klass) { return(this.constructor klass) } Object.prototype.isA bject.prototype.kindOf unction(klass) { if (this.instanceOf(klass)) return(true) if (this["mixins"] ! ndefined && this.mixins.includes(klass)) return(true) return(false) } Object.prototype.methods unction() { var result ] for (var property in this) if (typeof(this[property]) "function") result.push(property) return(result) } Object.prototype.respondTo unction(method) { return(this.methods().includes(method)) } Object.prototype.send unction(method) { var rest rguments.toArray().last(-1) if (!this.respondTo(method)) throw("undefined method") return(this[method].apply(this, rest)) } Object.prototype.instanceEval unction(code) { if (code.isA(Function)) return(code.apply(this)) else return(eval(code.toString())) } Number.prototype.times unction(block) { for (var i ; i < this; i++) block(i) } Number.prototype.upto unction(other, block) { for (var i his; i < ther; i++) block(i) } Number.prototype.downto unction(other, block) { for (var i his; i > ther; i--) block(i) } Number.prototype.towards unction(other, block) { var step his.cmp(other) for (var i his; i ! other - step; i - tep) block(i) } Number.prototype.succ unction() { return(this + 1) } Number.prototype.pred unction() { return(this - 1) } Number.prototype.chr unction() { return(String.fromCharCode(this)) } enumerable ew Object() enumerable.eachWindow unction(window, block) { if (!window.isA(Range)) window ange(0, window) elements ], pushed this.each(function(item, index) { elements.push(item) pushed + if (pushed % window.rend 0) { start 0, window.start - window.rend + pushed].max() end 0, window.rend + pushed].max() block(elements.fetch(xrange(start, end)), index) } }) } enumerable.collect numerable.map unction(block) { var result ] this.each(function(item, index) { result.push(block(item, index)) }) return(result) } enumerable.toArray numerable.entries unction() { return(this.map(function(item) { return(item) })) } enumerable.inject unction(firstArg) { var state, block, first rue if (arguments.length 1) { block irstArg } else { state irstArg block rguments[1] } this.each(function(item, index) { if (first && typeof(state) "undefined") state tem, first alse else state lock(state, item, index) }) return(state) } enumerable.find numerable.detect unction(block) { var result, done this.each(function(item, index) { if (!done && block(item, index)) { result tem done rue } }) return(result) } enumerable.findAll numerable.select unction(block) { return(this.inject([], function(result, item, index) { return(block(item, index) ? result.add(item) : result) })) } enumerable.grep unction(obj) { return(this.findAll(function(item) { return(obj.test(item)) })) } enumerable.reject unction(block) { return(this.select(function(item, index) { return(!block(item, index)) })) } enumerable.compact unction() { return(this.select(function(item) { return(typeof(item) ! undefined") })) } enumerable.nitems unction() { return(this.compact().length) } enumerable.sortBy unction(block) { return(this.map(function(item, index) { return([block(item, index), item]) }).sort(function(a, b) { return(a[0].cmp(b[0])) }).map(function(item) { return(item[1]) })) } enumerable.all unction(block) { return(this.findAll(block).length this.length) } enumerable.any unction(block) { return(typeof(this.find(block)) ! undefined") } enumerable.includes unction(obj) { return(this.any(function(item) { return(item obj) })) } enumerable.index unction(obj) { var result this.find(function(item, index) { if (obj item) { result ndex return(true) } else { return(false) } }) return(result) } enumerable.uniq unction() { return(this.inject([], function(result, item) { return(result.includes(item) ? result : result.add(item)) })) } enumerable.max unction(block) { if (!block) block unction(a, b) { return(a.cmp(b)) } return(this.sort(block).last()) } enumerable.min unction(block) { if (!block) block unction(a, b) { return(a.cmp(b)) } return(this.sort(block).first()) } enumerable.partition unction(block) { var positives ], negatives ] this.each(function(item, index) { if (block(item, index)) positives.push(item) else negatives.push(item) }) return([positives, negatives]) } enumerable.zip unction() { var ary rguments.toArray() ary.unshift(this) return(ary.transpose()) } enumerable.flatten unction(depth) { if (depth undefined) depth 1 if (!depth) return(this) return(this.inject([], function(result, item) { var flatItem tem.respondTo("flatten") ? item.flatten(depth - 1) : [item] return(result.merge(flatItem)) })) } Array.fromObject unction(obj) { if (!obj.length) throw("Can't convert") var result ] for (var i ; i < obj.length; i++) result.push(obj[i]) return(result) } Array.prototype.transpose unction() { var result, length 1 this.each(function(item, index) { if (length < 0) { /* first element */ length tem.length result rray.withLength(length, function() { return(new Array(this.length)) }) } else if (length ! tem.length) { throw("Element sizes differ") } item.each(function(iitem, iindex) { result[iindex][index] item }) }) return(result) } Array.withLength unction(length, fallback) { var result null].mul(length) result.fill(fallback) return(result) } Array.prototype.each unction(block) { for (var index ; index < this.length; ++index) { var item his[index] block(item, index) } return(this) } Array.prototype.extend(enumerable) Array.prototype.isEmpty unction() { return(this.length 0) } Array.prototype.at rray.prototype.fetch unction(index, length) { if (index.isA(Range)) { var end ndex.rend + (index.rend < 0 ? this.length : 0) index ndex.start length nd - index + 1 } if (length undefined) length if (index < 0) index + his.length var result his.slice(index, index + length) return(result.length 1 ? result[0] : result) } Array.prototype.first unction(amount) { if (amount undefined) amount return(this.at(xrange(0, amount))) } Array.prototype.last unction(amount) { if (amount undefined) amount return(this.at(range(-amount, -1))) } Array.prototype.store unction(index) { var length , obj arguments rguments.toArray() arguments.shift() if (arguments.length 2) length rguments.shift() obj rguments.shift() if (!obj.isA(Array)) obj obj] if (index.isA(Range)) { var end ndex.rend + (index.rend < 0 ? this.length : 0) index ndex.start length nd - index + 1 } if (index < 0) index + his.length this.replace(this.slice(0, index).merge(obj).merge(this.slice(index + length))) return(this) } Array.prototype.insert unction(index) { var values rguments.toArray().last(-1) if (index < 0) index + his.length + 1 return(this.store(index, 0, values)) } Array.prototype.update unction(other) { var obj his other.each(function(item) { obj.push(item) }) return(obj) } Array.prototype.merge rray.prototype.concat Array.prototype.add unction(item) { return(this.merge([item])) } Array.prototype.clear unction() { var obj his this.length.times(function(index) { delete obj[index] }) this.length } Array.prototype.replace unction(obj) { this.clear() this.update(obj) } Array.prototype.mul unction(count) { var result ] var obj his count.times(function() { result esult.merge(obj) }) return(result) } Array.prototype.fill unction(value) { var old_length his.length var obj his this.clear() var block if (typeof(value) ! function") block unction() { return(value) } else block alue old_length.times(function(i) { obj.push(block(i)) }) } Array.prototype.removeAt unction(targetIndex) { var result his[targetIndex] var newArray his.reject(function(item, index) { return(index targetIndex) }) this.replace(newArray) return(result) } Array.prototype.remove unction(obj) { this.removeAt(this.index(obj)) } Array.prototype.removeIf unction(block) { this.replace(this.reject(block)) } function Range(start, end, excludeEnd) { this.begin his.start tart this.end nd this.excludeEnd xcludeEnd this.rend xcludeEnd ? end.pred() : end this.length his.toArray().length } function range(start, end) { return(new Range(start, end)) } function xrange(start, end) { return(new Range(start, end, true)) } Range.prototype.toString unction() { return("" + this.start + (this.excludeEnd ? "..." : "..") + this.end) } Range.prototype.each unction(block) { var index this.start.towards(this.rend, function(i) {return(block(i, index++))}) } Range.prototype.extend(enumerable) Range.prototype.includes unction(item) { return(this.start.cmp(item) -1 && this.rend.cmp(item) +1) } function Hash(defaultBlock) { this.defaultBlock efaultBlock this.keys ] this.values ] this.length } Hash.fromArray unction(array) { var result ew Hash() array.each(function(item) { var key tem[0], value tem[1] result.store(key, value) }) return(result) } Hash.prototype.at ash.prototype.fetch unction(key, block) { var result if (this.hasKey(key)) result his["item_" + key.hash()] else { if (block) result lock(key) else result efaultBlock(key) } return(result) } Hash.prototype.store unction(key, value) { this.keys.push(key) this.values.push(value) this.length++ return(this["item_" + key.hash()] alue) } Hash.prototype.toA unction() { return(this.keys.zip(this.values)) } Hash.prototype.isEmpty unction() { return(this.length 0) } Hash.prototype.has ash.prototype.includes ash.prototype.hasKey unction(key) { return(hasOwnProperty("item_" + key.hash())) } Hash.prototype.hasValue unction(value) { return(this.values.includes(value)) } Hash.prototype.each unction(block) { this.toA().each(function (pair) { return(block(pair[1], pair[0])) }) } Hash.prototype.extend(enumerable) Hash.prototype.merge unction(other) { other.each(function(value, key) { this.store(key, value) }) } Hash.prototype.remove unction(key) { var valueIndex his.keys.index(key) var value his.values[valueIndex] this.keys.remove(key) this.values.removeAt(valueIndex) delete(this["item_" + key.hash()]) this.length-- return([key, value]) } Hash.prototype.removeIf unction(block) { this.each(function(value, key) { if (block(value, key)) this.remove(key) }) } Hash.prototype.shift unction() { return(this.remove(this.keys[0])) } Hash.prototype.clear unction() { var obj his this.length.times(function() {obj.shift()}) } Hash.prototype.replace unction(obj) { this.clear() this.merge(obj) } Hash.prototype.invert unction() { return(Hash.fromArray(this.map(function(value, key) { return([value, key]) }))) } Hash.prototype.rehash unction() { var result ew Hash(this.defaultBlock) this.each(function(value, key) { result.store(key, value) }) this.replace(result) } function MatchData(matches, str, pos) { this.matches atches, this.string tr this.begin his.position os this.match atches[0] this.captures atches.slice(1) this.end os + this.match.length this.length atches.length this.preMatch tr.substr(0, pos) this.postMatch tr.substr(this.end) } MatchData.prototype.toString unction() { return(this.match) } MatchData.prototype.at unction(index) { return(this.matches.at(index)) } MatchData.prototype.toArray unction() { return(this.matches) } RegExp.prototype.match unction(str) { var matches if (matches his.exec(str)) { var pos tr.search(this) return(new MatchData(matches, str, pos)) } } String.prototype.clone unction() { return(new String(this)) } String.prototype.each unction(block) { this.split("\n").each(block) } String.prototype.extend(enumerable) String.prototype.toArray unction() { return(this.split("\n")) } String.prototype.towards unction(other, block) { var item his while (item.cmp(other) < ) { block(item) item tem.succ() } } String.prototype.hash unction() { var result this.split("").each(function(item) { result + tem.charCodeAt(0) result + result << 10) result ^ result >> 6) }) result + result << 3) result ^ result >> 11) result + result << 15) return(result) } String.prototype.chars unction() { return(this.split("")) } String.prototype.at tring.prototype.fetch unction(index, length) { if (index.isA(Range)) { var end ndex.rend + (index.rend < 0 ? this.length : 0) index ndex.start length nd - index + 1 } if (length undefined) length if (index < 0) index + his.length return(this.substr(index, length)) } String.prototype.store tring.prototype.change unction(index) { var length , obj arguments rguments.toArray() arguments.shift() if (arguments.length 2) length rguments.shift() obj rguments.shift() if (index.isA(Range)) { var end ndex.rend + (index.rend < 0 ? this.length : 0) index ndex.start length nd - index + 1 } if (index < 0) index + his.length return(this.substr(0, index) + obj + this.substr(index + length)) } String.prototype.reverse unction() { return(this.split("").reverse().join("")) } String.prototype.scan unction(pattern) { var str his, result ], oldPos 1, match, offset while (match attern.match(str)) { if (match.end match.begin) throw("Can't have null length matches with scan()") var newMatch ew MatchData(match.matches, match.string, match.position + offset) result.push(newMatch) str atch.postMatch offset + atch.toString().length } return(result) } String.prototype.sub unction(what, by, global) { var block ypeof(by) "function" ? by : function() { return(by) } var matches his.scan(what), result his, offset if (!global && !by.global) matches atches.slice(0, 1) matches.each (function(match) { var replacement lock(match) offset + eplacement.length - match.toString().length result esult.change(match.begin + offset, match.toString().length, replacement) }) return(result) } String.prototype.gsub unction(what, by) { return(this.sub(what, by, true)) } String.prototype.tr unction(from, to) { var map ash.fromArray(from.chars().zip(to.chars())) return(this.chars().map(function(chr) { return(map.includes(chr) ? map.fetch(chr) : chr) }).join("")) } String.prototype.mul unction(other) { var result ", str his other.times(function() { result + tr }) return(result) } String.prototype.isUpcase unction() { return(this this.upcase()) } String.prototype.isDowncase unction() { return(this this.downcase()) } String.prototype.isCapitalized unction() { return(this.fetch(0).isUpcase() && this.fetch(range(1, -1)).isDowncase()) } String.prototype.upcase tring.prototype.toUpperCase String.prototype.downcase tring.prototype.toLowerCase String.prototype.capitalize unction() { return(this.fetch(0).upcase() + this.fetch(range(1, -1)).downcase()) } String.prototype.swapcase unction() { return(this.chars().map(function(chr) { if (chr.isUpcase()) return(chr.downcase()) if (chr.isDowncase()) return(chr.upcase()) return(chr) }).join("")) } String.prototype.ord unction() { return(this.charCodeAt(0)) } String.prototype.isEmpty unction() { return(this.length 0) } String.prototype.succ unction() { if (this.isEmpty()) return(this) /* numerics */ if (/^\d+$/.test(this)) return((Number(this) + 1).toString()) /* just one character */ if (this.length 1) { /* letters */ if (/[A-Za-z]/.test(this)) { var lastLetter his.isUpcase() ? 'Z' : 'z' var firstLetter his.isUpcase() ? 'A' : 'a' return((this lastLetter) ? firstLetter.mul(2) : (this.ord() + 1).chr()) } else { return(this (-1).chr() ? 0.0.chr().mul(2) : (this.ord() + 1).chr()) } /* multiple characters */ } else { var result his for (var index his.length; index > ; index--) { var chr his.at(index) if (chr.succ().length 1 || index 0) return(result.change(index, chr.succ())) else result esult.change(index, chr.succ().at(-1)) } } } String.prototype.ljust unction(length, fill) { if (!fill) fill " if (fill.length > 1) throw("TODO: Make fills with length > 1 work.") return(this + fill.mul(length / fill.length - this.length)) } --------------040404080407000006030407--