V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  FrankHB  ›  全部回复第 38 页 / 共 92 页
回复总数  1831
1 ... 34  35  36  37  38  39  40  41  42  43 ... 92  
2019-12-09 01:44:28 +08:00
回复了 whoops 创建的主题 Python Python 作用域问题,int 型变量为什么会有些特殊呢
@ipwx 基本意思分析对了,但引入了一些跟 Py 不见得有关的更麻烦的问题……不太容易直接说明白。
就干脆都过一遍吧。顺便当 FAQ 草稿。

首先,这里的问题,跟编译不编译没有关系。
所谓的编译原理只是顺带提到这些内容,因为这其实是语言设计而不是编译这种实现的先决知识,但没专门 PL 的同学就只能勉为其难一下了。

其次,这里的问题的知识背景,只要是典型的有所谓变量(variable) 的语言,纯解释实现一样普遍适用。
典型的这类语言中变量以源代码中的的特定片段,即变量名(variable name) ,通常以文本的形式提供,源代码中的实际表示通常就是字符串。
源代码的文本通过词法分析识别出作为词素(lexeme) 的实例,然后被分析归类成为某一类记号(token) ,这是附加语法用途的文本以外的构造,在语法分析中完成。
被作为变量名的记号是标识符。(有的语言在此之前还有预处理阶段,其中的类似的词素也叫标识符,但不属于记号—— 例如,C 的预处理记号在语法分析中被区分出表示变量名的普通的标识符记号,以及语法意义上的关键字。)
在典型的语言(排除文本宏替换这类 DSL )中,用户实际一般使用是和语法规则区分规定的语义规则明确的抽象,而非语法构造。
标识符在对应的语法处理之后就已经确定存在。(当然,语法上的处理不一定要求是全局 AOT 的形式,这个另当别论。)这和标识符表示什么含义是两回事。
用标识符去代替标识符指称的实体(这里是变量)讨论会显得稀里糊涂,因为实际的处理方式不唯一,而且经常依赖之后的语义处理过程,处理后的内容也没法一一对应(允许一一对应的平凡逻辑还浪费了语言允许的抽象能力,通常就是应该在语言设计中避免的)。

第三,大多数用户在这里没有区分清楚所谓“变量”所指的确切含义,于是稀里糊涂程度翻倍。
虽然不少语言设计中根本没说清楚什么叫变量,一般地,变量区分于其它语言概念的关键性质就是保证存在标识变量的变量名。
注意:
1.变量总是被命名。语言层面上没有所谓的“匿名变量”,因为这是逻辑上的自相矛盾。
2.变量名是标识符,但反过来不一定,因为标识符指称实体,但不一定命名变量。它可能是特殊的语法构造,如宏。
3.变量(的值)是不是支持可被修改,对是不是变量无关紧要。像纯函数式语言中就有不可修改的变量。(但是近来很多语言设计者会误用可修改的对象作为变量的含义,另当别论。)
4.有的语言中,函数名被单独区分,剩下的实体叫做对象(object) (注意先来后到,这和面向对象毫无关系),特指明确需要存储资源的、可以“储存”值(value) 并可能明确支持修改值的实体,如 C (题外话,ISO C 直接回避了“变量”的概念)。其它一些语言不强调这点,可以把函数也作为对象。
实际上严格定义(如 IEC 2382 )中变量可被形式化为命名变量的标识符、指称(denote) 的实体(entity) 和上下文信息的元组。
其中,上下文一般能明确被指称的实体在不同位置中不冲突,也就是源代码中允许引入相同的标识符指称不同实体。
为了消歧义,可以利用上下文中不同的作用域(scope) ,通过名称解析(name resolution) 明确某个标识符作为变量名无歧义的指称到底是同名变量的哪一个。这是语义分析中的一种基本操作。
而用户使用一个变量,既用的是变量名,也可以仅是变量指称的实体。日常所谓的“变量”可能只是指后者,都是严格意义上的变量。为了突出变量构成中的实体以外的作用,可以强调为变量绑定(variable binding) (这也可以是实现名称解析时使用的数据结构之一)。而绑定一个变量则指在程序中引入变量绑定的操作。
用户阅读源代码,看到的首先是语法上的标识符,然后也需要人肉做名称解析以完成可能需要的消歧义,以确定变量到底指称什么实体,才能明白含义。
人肉实现名称解析,它的结果在字面含义上,就是实体的引用(reference) 。
虽然一般用户不一定意识到这点,但实际上语言的机制比一般人直接见名知意复杂得多。这是因为语言的规则要求明确性,需要处理所有情形,又要和其它语法一致。
所以典型的语言中,这不是简单的语法替换过程,而是以标识符构成表达式(expression) ,对表达式求值(evaluate) 之后确定表达式具有的值(value) 。
标识符构成的表达式的求值具有这样的性质:若被求值的表达式中的标识符指称一个实体,则求值后表达式的值引用被指称的实体。
这个意义上,表达式的值同样也是所谓的引用(reference) 。
虽然具体语言设计中不一定提供一等引用(first-class reference) 给用户,但只要是通过表达式求值而不是直接语法替换的形式提供变量名称解析、同时需要区分变量同一性(identity) (基本上只要不是纯函数语言就不可能回避)的语言设计,不可能避免等价于这里的引用的概念。例如,C 没提供引用,但它有左值(lvalue) 。
所以语法意义上标识符确实就只是标识符,但唐突和对象或引用割裂开来,是无助于分清楚这些理由的。

最后,对比上面的通用设计框架,顺带看看 Python 的具体规定。(以下照搬 3.8 的文档,URL 略。)
2.3. Identifiers and keywords
Identifiers (also referred to as names) are described by the following lexical definitions.
...
[一坨具体语法略。]
……果然比上面说得还简单。
3.1. Objects, values and types
Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects. (In a sense, and in conformance to Von Neumann’s model of a “stored program computer,” code is also represented by objects.)
这里对象用的是存储实体的概念。
The value of some objects can change. Objects whose value can change are said to be mutable; objects whose value is unchangeable once they are created are called immutable. (The value of an immutable container object that contains a reference to a mutable object can change when the latter’s value is changed; however the container is still considered immutable, because the collection of objects it contains cannot be changed. So, immutability is not strictly the same as having an unchangeable value, it is more subtle.)
...
Python 不提供一等引用,但引用在语言规范中就没被回避。(否则一坨 reference-counting 就更没法说了。)
4.2. Naming and binding
Names refer to objects. Names are introduced by name binding operations.
The following constructs bind names: formal parameters to functions, import statements, class and function definitions (these bind the class or function name in the defining block), and targets that are identifiers if occurring in an assignment, for loop header, or after as in a with statement or except clause. The import statement of the form from ... import * binds all names defined in the imported module, except those beginning with an underscore. This form may only be used at the module level.
A target occurring in a del statement is also considered bound for this purpose (though the actual semantics are to unbind the name).
Each assignment or import statement occurs within a block defined by a class or function definition or at the module level (the top-level code block).
If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal or global. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.
Each occurrence of a name in the program text refers to the binding of that name established by the following name resolution rules.
4.2.2. Resolution of names
A scope defines the visibility of a name within a block. If a local variable is defined in a block, its scope includes that block. If the definition occurs in a function block, the scope extends to any blocks contained within the defining one, unless a contained block introduces a different binding for the name.
When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment.
When a name is not found at all, a NameError exception is raised. If the current scope is a function scope, and the name refers to a local variable that has not yet been bound to a value at the point where the name is used, an UnboundLocalError exception is raised. UnboundLocalError is a subclass of NameError.
If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.
到这里为止,LZ 的问题也好引用的理解也罢,包括具体报错的理由,应该都比较明确了。
Python 的设计和一众小作坊设计一样共享一个经典糟粕——赋值这个依赖已有对象的(修改对象的值)操作和引入变量绑定这两种逻辑上根本不同(绑定原则上要求指定的变量绑定不存在,赋值要求变量绑定在之前必须存在)的操作混在一起了。
所以在人肉解析名称之前,读者还需要多做一次消歧义,先确定这到底是个真正(纯粹)的赋值,还是带变量绑定的所谓赋值。否则就可能出现 LZ 这样的稀里糊涂。
虽然这个例子里要消歧义很简单(都不用照抄 Python 实现的语义,重写 cnt = 0 成为类似 let cnt = 0 这样的伪码,总之能跟后面真正的赋值区分清楚即可),使用户一般性地被迫阅读至少整个块才能做到确定有哪些局部变量绑定是明显糟烂的设计。
(正常的设计中,变量绑定是单独的操作,这往往被设计成变量的初始化声明的语法单独提供。Python 文档在这方面倒有些自知之明,知道是 subtle,但实际上为了使“块中到处可用”也不需要这样的设计,把声明改成表达式即可。)
@Athrob 继续脑洞一下……网络技术到要真能发展到用户能对带宽可用性甚至成本都满不在乎的情形,可能再晚些年满大街都是人机融合人了……对植入人体的计算机来讲,物理距离的限制仍然会发挥作用;安全需求也要求隔离。这样一看,这些计算机就像是现在的桌面和手持设备一样直接能被人操控,而这以外的计算机都是属于网络而不是个人控制的公有“云”。
……好像人能直接操控的距离反过来还减小了,怎么觉得是在开倒○。。。
@Athrob 光速有限是指响应上的物理限制会让空间换时间的策略失效而必须从设计之初正面应对做好变通。比如说,现在的时钟频率已经让集成电路布线已经要考虑这个限制了。当然,网络没那么极端,但因为因果律限制,凡涉及到用户输入输出的交互,会有同样来自光速的限制。比如在线游戏用户的操作,几十毫秒的延迟可能就是省不掉的。所以只要尺度够大,物理上近一些的在一些关键问题上就是一定更占便宜,有时候可能会决定可行性;网络技术再怎么发展这都没法改变。
能改善的主要是吞吐量。但就算技术允许上限提高和单位传输的数据成本下降,这里总成本一直感人嘛……而且和计算资源一样,很难想象带宽过剩是什么情况。“网络跟电力一样是必备的,不再有带宽或线路之分”最后无非是用户不需要计较带宽具体有多少。然而物理上这些资源不可能凭空生出来,就要服务商做基建投入。羊毛是出在谁身上的呢……
2019-12-07 23:59:59 +08:00
回复了 sadhen 创建的主题 程序员 大家愿意成为桌面软件(Windows/macOS) 的付费订阅用户么?
@sadhen 你要问有没有,那肯定是有——我就有。
我现在日用的 Windows 桌面软件里就有从已经停止支持或者明确废弃支持的开源软件里改的:
Markdown 编辑器用的 MdCharm,作者个人原因停止维护了,我改用 MSYS2 的 Qt,有些依赖问题要自己解决;
Firefox 不支持 UXP 然后我就改用 Baskilisk ( Waterfox 和我的 Profile 有兼容问题没法用),后来 Basilisk 砍了 WebExtension 支持,我就自己拿砍掉的代码糊回去了,一直好好的(除了放源码的机器最近坏了……)。
但是我的例子没法有代表性:我自己会整当然直接自己整了,而且我还没遇到过我整不了别人就恰好能整的……所以这个只是需求的例子,不是付费意愿的例子,pass。
在是否有意愿付费之前你还应该会遇到的更直接的问题是,不同用户之间要恰好有相同的确切需求的可能性太小,所以可能得你来推荐软件看看正好有没有顶用的,但是要太小众了,可能谁都没用上;这就是两难问题了。
2019-12-07 23:26:24 +08:00
回复了 sadhen 创建的主题 程序员 大家愿意成为桌面软件(Windows/macOS) 的付费订阅用户么?
@sadhen 如果你只是能保证让非特定最终用户(特别是个人桌面用户)能体验到正常“可用”而不是面向特定业务提供解决方案,并没有另外提供原始许可证以外的担保的话,我估计至少这里不太容易有多少人能开出有意义的价钱——实际上大部分回复直接说不买账了。根本上,你并没比原有免费的产品提供很多东西(就算你客观上有不小的成本)。对非常有明确和迫切需求的用户自然另当别论,但这不按个别软件具体来谈基本是没什么意义的。
另一方面,如果不管付费意愿,虽然有需求的用户绝对数量应该不少,但在桌面用户中还是占极少数。可能大部分人都没听说过你提供的非 Windows 平台的软件——而听说过的,大概又有不少像这里一样的态度的。这样你的渠道成本也极有可能成问题。
所以这个模式运气好也许能让你赚点外快;要成规模对“很多”的软件下手,商业上相当困难(更不说桌面软件的技术栈现在还是一片混乱了)。道理上讲,这比像深度这类有明确目标而受到政策支持的大厂业务还麻烦。
当然,以上只是我现在的个人判断,也没法断言绝对不可行。如能最终回馈贡献,还是祝你好运。
2019-12-07 23:11:51 +08:00
回复了 sadhen 创建的主题 程序员 大家愿意成为桌面软件(Windows/macOS) 的付费订阅用户么?
@sadhen 你只说清楚了订阅,也就是肯定要用户如何付钱;但你自己具体保证提供什么都没说清楚:
你能直接上阵移植尚未有支持的产品,还是只负责已有上游移植支持(但可能不成熟)的产品?
你是否对用户提供何种可用性,还是完全不提供在原有许可证上的附加担保?
你是否按用户需要,提供和上游不同的安全性和功能缺陷的修复和支持策略?
你是否总是能直接负责提供自己就是著作权人的修改(而非做中间商)并对你的修改直接引入的问题负责?
你是能直接响应用户关于功能扩充的定制需求(而不只是当传话筒)?
你是否保证不捆绑专有依赖或者引入专有技术的服务?
你能否提供承诺和计划,保证你的有效的修改可以及时分发给公众并回馈给上游?
……
我要说这些,是因为这些工作的内容很不一样,即使是同一个市场背景下,合理的价码也不一样。全部用订阅这种付费形式糊弄过去是一种狡猾的手段。
你连确切卖什么服务都不说清楚,这是要人怎么确认是否有这个需求?还是说,你所谓了解需求,其实只是在试探有多少人能对稀里糊涂花钱不在意,以便通过欺负用户和你信息普遍上的不对等,来让更占便宜?在一般意义上,这就是智商税。
不是扣帽子,收这种智商税的确可以是合法的商业模式,但做得太明显就不好看了,特别这里的不少用户还真不那么愿意傻乎乎的。
@Athrob 光速一直是有限的,谢谢理解。
LLVM IR 是没戏一桶浆糊的。这玩意儿它存在的意义主要是让脑子不够好使到接受不了 CPS 之类的用户读写而已——然而这样的用户本来就不成气候;而 explicit SSA IR 远远也没简单到让剩下大多开发者日常能看能写的程度。因为本质上在结构化扩展性上是残的,根本不可能通过语法扩展取代高级语言前端之间的翻译;想自己扩充功能的用户有 IR 也多大没卵用,照样要跪在不稳定的 API 面前。
WASM 原来有甩掉这个缺陷的机会,不过给它自己糟践了,不提也罢。不过可笑的是,诸如格林斯潘第十定律和这里山寨的所谓的终结者定律原始都是用在具有(或者至少理论上允许直接修改局部特性扩充出来)同像性的语言上,WASM 这个恰恰就把这坨阉了……年轻人,还真敢说啊。
现在大抵是看透了,以二进制规格开始吹的,要么老实点不要想着一桶浆糊,否则还是都凉凉好了,别没事找事。
原来搞 Web 的另说,对圈外人来讲,撑死就是又多了个争风吃醋的 target 多找点事添乱而已。(对不少应用开发者来讲,还不如整活个干净点的 XUL 有意义。)
WASM 一开始的设计还有些新玩意儿,不过 AST 出局以后 Web 外也没什么标新立异的资本了。大概名字是原罪吧。
2019-12-07 22:10:52 +08:00
回复了 wikinee 创建的主题 程序员 如果对一门语言感兴趣但是工作中用不到怎么办?
反省动机。
你对别的语言感兴趣的缘由是“看到很多公司”怎么样,这是不是和你工作相关的内容?
那么,你得先问问自己:到底是真的对语言感兴趣呢,还是对工作技能、换岗和以后的其它出路更感兴趣?
你了解了语言,除了满足你的这部分明显的兴趣以外还打算干什么?如果没有更进一步的明确目的,那到底也是为了工作,还是没法马上用上的——于是也就是花时间投机而已。
2019-12-07 22:02:01 +08:00
回复了 sadhen 创建的主题 程序员 大家愿意成为桌面软件(Windows/macOS) 的付费订阅用户么?
卖服务就直说,不要搭售智商税。
原来 KDE for Windows 就有自带上百个包的官方版,现在缩水了改叫 KDE on Windows Initiative,在 choco 上也有 KDevelop 能用。你要自己另外搞一坨,整体要提供什么不同的支持?还是说就只是你挑出个别 KDE 软件移植?

@janus77 GCC 明确 Win32 就是 Secondary Platform (i686-mingw32) ,各种 sanitizer 现在还是残的。还是你管这个叫小众?
2019-12-07 15:51:20 +08:00
回复了 515576745 创建的主题 程序员 眼镜党求推荐无线头罩式耳机 -> QC35 \ 1000XM3
黑框有啥特别含义么……基本上很难有奇葩的颜色搭配吧。
2019-12-07 15:39:42 +08:00
回复了 wsseo 创建的主题 程序员 国产浏览器在国内的用户还是很多的
@leafre 不用看这贴回复,都该退网了。
都是拿着一坨“文档”强行“动态”打肿脸充胖子强装有多少有效交互的所谓 Web Agant 来 dssq 的屑用户,还谁真能有脸站在鄙视链上了?
或者说,这里有几个日过 Project Xanadu 的?有几个比被自己翻过的东西制造出了更大的先进技术影响的?
2019-12-07 15:09:32 +08:00
回复了 wsseo 创建的主题 程序员 国产浏览器在国内的用户还是很多的
@okjb 完美?
插件?没 UXP+WebExtensions 就够废了。
同步? https://forum.palemoon.org/viewtopic.php?t=21091
2019-12-07 15:03:12 +08:00
回复了 wsseo 创建的主题 程序员 国产浏览器在国内的用户还是很多的
@yukiloh 我用我自己魔改的,这要能算国产的话,就不是。
这个 ranking 的地区数据来源是啥。不公开具体位置的忽略是么?
2019-12-07 14:57:39 +08:00
回复了 Myprincess 创建的主题 程序员 奇怪: EBAY 干掉密码为何 V2 上有没有讨论
不是用户,没注意到。
看了下,做了件原则上看起来正确但是实际效果可能很呵呵的事。
完了,待久了语文退化了……不完全互斥→完全不互斥……
@dxgfalcongbit 社交活动要花费时间精力,不完全互斥是不可能的。你要强行并行当一件事……跟屌丝谈恋爱?
@changjiangzzZ 了解了,谢谢。
1 ... 34  35  36  37  38  39  40  41  42  43 ... 92  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1422 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 27ms · UTC 17:29 · PVG 01:29 · LAX 09:29 · JFK 12:29
Developed with CodeLauncher
♥ Do have faith in what you're doing.