惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Forbes - Security
Forbes - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
L
LangChain Blog
量子位
GbyAI
GbyAI
B
Blog RSS Feed
月光博客
月光博客
人人都是产品经理
人人都是产品经理
腾讯CDC
Recent Announcements
Recent Announcements
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
The Cloudflare Blog
D
Docker
Cyberwarzone
Cyberwarzone
U
Unit 42
NISL@THU
NISL@THU
C
Check Point Blog
B
Blog
大猫的无限游戏
大猫的无限游戏
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
G
GRAHAM CLULEY
Engineering at Meta
Engineering at Meta
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
P
Proofpoint News Feed
F
Fortinet All Blogs
V
V2EX
T
Threat Research - Cisco Blogs
T
Threatpost
S
SegmentFault 最新的问题
Know Your Adversary
Know Your Adversary
雷峰网
雷峰网
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园 - 司徒正美
P
Privacy & Cybersecurity Law Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
TaoSecurity Blog
TaoSecurity Blog
Latest news
Latest news
Apple Machine Learning Research
Apple Machine Learning Research
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Y
Y Combinator Blog
P
Privacy International News Feed
L
Lohrmann on Cybersecurity
AWS News Blog
AWS News Blog
G
Google Developers Blog
美团技术团队

Secret Weblog

Becoming More Xee: A Modern XPath and XSLT Engine in Rust Looking for new challenges! Repeat Yourself, A Bit The Curious Case of Quentell The Humble For Loop in Rust The Humble For Loop in JavaScript Don Question Best Practices I Was a 1980s Teenage Programmer Part 5: Achieving Assembly I Was a 1980s Teenage Programmer Part 4: The Call of Assembly The Tooling Shift I Was a 1980s Teenage Programmer Part 3: MSX-2 JavaScript: when you need two ways to do it! Empowering Programming Languages Bloat and Retrofuturism Refreshing my Blog Again Random Rust Impressions Apilar: An Alife System I Was a 1980s Teenage Programmer Part 2: Olivetti M24 I Was a 1980s Teenage Programmer: the Alphatronic SolidJS fits my brain Is premature optimization the root of all evil? Framework Patterns: JavaScript edition Roll Your Own Frameworks Framework Patterns Secret Weblog Highlights Refactoring to Multiple Exit Points mstform: a form library for mobx-state-tree Seven Years: A Very Personal History of the Web Morepath 0.16 released! Is Morepath Fast Yet? Introducing Bob Strongpinion Punctuated Equilibrium in Software Morepath 0.15 released! Impressions of React Europe 2016 Morepath 0.14 released! Morepath 0.13 now with Dectate Dectate: advanced configuration for Python code JavaScript Dependencies Revisited: An Example Project The Incredible Drifting Cyber A Brief History of Reselect The Emerging GraphQL Python stack Thoughts about React Europe Build a better batching UI with Morepath and Jinja2 GraphQL and REST Server Templating in Morepath 0.10 10 reasons to check out the Morepath web framework in 2015 A Review of the Web and how Morepath fits in Morepath 0.9 released! Better REST with Morepath 0.8 Morepath 0.7: new inter-app linking They say something I don Life at the Boundaries: Conversion and Validation BowerStatic 0.4 released! Morepath 0.6 released! Morepath 0.5(.1) and friends released! New HTTP 1.1 RFCs versus WSGI Against On Naming In Open Source My visit to EuroPython 2014 Morepath 0.4.1 released (with Python 3 fixes) Morepath 0.4 and breaking changes Announcing BowerStatic Morepath 0.3 released! Morepath 0.2 Morepath Python 3 support The Call of Python 2.8 Morepath 0.1 released! WebOb and Werkzeug compared Morepath: from Werkzeug to WebOb Racing the Morepath: SQLAlchemy Integration The Centre Cannot Hold Breaking Morepath Changes Morepath Update How to do REST with Morepath Morepath Security the Gravity of Python 2 #python2.8 discussion channel on freenode Alex Gaynor on Python 3 Morepath Documentation Starting to Take Shape Back to the Center Morepath App Reuse Implementing Grok Grok: the Idea Why Linux Works for Me On the Morepath The New Zope as a Web Framework Jim Fulton, Zope Architect Renewing Zope Object Publishing The Weirdness of Zope The Rise of Zope My Exit from Zope Reg: Component Architecture Reimagined JSConf EU 2013 impressions Obviel 1.0! JS Dependency Tools Redux Obviel 1.0rc1 released! Succinct data structures
Reg, Now With More Generic!
Martijn Faassen · 2013-10-28 · via Secret Weblog

A month ago I first announced the Reg library for Python. After posting it I got a comment asking why I didn't just use simplegeneric or PEP 443? One important reason is that I wasn't aware them. The other reason is that I want some special features. But it did get me thinking. Thanks commenter yesvee!

PEP 443

So what's PEP 443? It proposes functionality that lets you create generic functions that dispatch on their first argument (single dispatch):

from functools import singledispatch
@singledispatch
def fun(arg):
    return "The default"

@fun.register(int)
def int_fun(arg):
    return "Int argument"

@fun.register(list)
def list_fun(arg)
    return "List argument"

When you now call fun() it will dispatch to different implementations dependent on the type of the first argument:

>>> fun(1)
"Int argument"

>>> fun([])
"List argument"

>>> fun('foo')
"The default"

The advantage: dispatch on type, which is useful to extend classes from the outside, but just functions to the end user.

The Zope Component Architecture

Reg is the Zope Component Architecture (ZCA) reimagined. The ZCA is interface-centric. Objects are looked up by interface, and an interface looks a lot like a class. Here's what it looked like with Reg (which has a simpler registration API):

import reg

class IFunctionality(reg.Interface)
    pass

def int_fun(arg):
    return "Int argument"

def list_fun(arg)
    return "List argument"

r = reg.Registry()
r.register(IFunctionality, [int], int_fun)
r.register(IFunctionality, [list], list_fun)

And then this is how you'd use it:

>>> IFunctionality.adapt(1)
"Int argument"
>>> IFunctionality.adapt("List argument")
"List argument"

This API was in fact slightly less good as you could accomplish with the ZCA itself:

>>> IFunctionality(1)
"Int argument"
>>> IFunctionality("List argument")
"List argument"

This is because I wanted to keep Reg simpler, and the ZCA has to do quite a lot of wizardy to make the latter functionality work. But I actually wanted it in Reg. And that starts to look suspiciously like a generic function implementation.

So I started thinking about rewriting Reg so it presented itself much like generic functions as in PEP 443, but with special Reg sauce added. I talked it over with a few people at PyCon DE too. Thanks for helping me clarify my thinking!

All New Generic Reg

So last week I refactored Reg so be generic function based. Gone is lookup by interface, in is generic function calling. Here's what it looks like with Reg today:

import reg

@reg.generic
def fun(arg):
    return "The default"

def int_fun(arg):
    return "Int argument"

def list_fun(arg)
    return "List argument"

r = reg.Registry()
r.register(fun, [int], int_fun)
r.register(fun, [list], list_fun)

And using it looks like a normal function call, just like in PEP 443:

>>> fun(1)
"Int argument"

Reg doesn't deal with interfaces anymore. Interfaces tend to scare off Python developers as they're a new concept, and I realize they just weren't necessary anymore. Now people using your Reg-based APIs just use functions, like with any other API.

Why not use the decorator approach to register generic function implementations? Because Reg allows more than one registry. While writing this I realize that's not a good answer: I can provide this in Reg if I make the decorator a method on Registry. Stay tuned!

But anyway, Morepath, the web framework built on Reg that I'm working on, already supplies a decorator like this that integrates with its configuration engine.

Why Reg instead of PEP 443?

So what's the special Reg sauce? Why not just use PEP 443? Reg offers a few facilities that I needed in Morepath:

  • Multiple dispatch. PEP 443 offers single dispatch on the first argument. Reg implements multiple dispatch, on multiple arguments. This is handy when you're implementing a web framework such as Morepath, which dispatches on request and model.
  • You can isolate one set of generic implementation function implementations from another one in the same runtime. This is because Reg allows more than one registry in which these can be registered.
  • Registries can also be composed together. This allows a core framework to register some implementations and application code some more.
  • The registry to use can be implicit, or you can be totally explicit about what registry to use when you call a generic function.
  • Get all the generic functions that would apply to arguments. Register other things than functions and still look them up. I use these advanced use cases in Morepath in a few places.
  • Predicate support. The Pyramid web framework lets you register views not only by type, but also by other things, such as HTTP request method (GET, POST, etc). I've put support for this kind of thing in Reg itself, and I use it in Morepath. This bit is still underdocumented, please stay tuned!

Luckily you don't have to commit to Reg. You could implement your API using the more modest PEP 443 implementation first, and then switch to Reg should you discover its features would be helpful to you. You'd have to change how you register the implementations of generic functions, but not the API itself.

The New Reg Docs

I've updated and extended the Reg docs. Read the usage docs and check out the all new API documentation!

This should help you get started using Reg.

Road to Morepath

Reg is foundational to Morepath, the up and coming Python micro web framework with super powers. I've adjusted Morepath to use the new generic Reg. The morepath code is online. Stay tuned for docs!