V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  secondwtq  ›  全部回复第 79 页 / 共 123 页
回复总数  2447
1 ... 75  76  77  78  79  80  81  82  83  84 ... 123  
2019-09-28 23:51:11 +08:00
回复了 amiwrong123 创建的主题 程序员 Java 泛型方法与通配符 其中的类型推断该如何理解?
@amiwrong123
我也是最近也开始研究 subtyping,我发现一个规律是 covariance 和 contravariance 一般是对称的,这个问题可以从这个角度出发理解:
Holder<?>,这里的 ? 可能是任何类型 X

在 T wildSubtype(Holder<? extends T> holder, T arg) 中,可以直接把 T 推断为 Object,注意 Object 是 Top Type,是任何类型的 supertype (包括它自己),X <: T 这个 constraint 对任意 Holder<X> 都成立,X 既可以是 Integer,也可以是 InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState

在 T void wildSupertype(Holder<? super T> holder, T arg) 中,没有合适的 ?:
假设 X 是 Object,然后我们的 constraint 是 T <: X,然后既然 X 是任意的类型,那么这个 T 应该直接推断成 Bottom Type,也就是 null,所以 wildSupertype(unbounded, null) 是可以过编译的
但是你给的 lng,无论把 T 推断成 Long/Number/Object 等等都是错的,比如 T 是 Object,那么 X 就只能是 Object,T 是 Long,那 X 就只能是 Long/Number/Object/Serializable ... 无论哪种情况,如果 我的 Holder<?> 实际上是一个 Holder<HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor>,T <: X 就不成立了
很纳闷不用 FCPX 的话为啥要用白苹果剪视频 ...
2019-09-28 13:59:40 +08:00
回复了 BruceAuyeung 创建的主题 程序员 c++动态调用链接库的问题
首先楼主这个问题和 C++ 没关系,其实应该算是 Linker/Loader/ABI 的范畴,传统上算是 C (”学会 C 语言“在现在的语境下已经包含了太多的东西了)。

可以把原问题大致分成两个部分:
第一是定位并载入动态库以及库中的符号,这一步完成之后会给你一个函数代码的指针。而楼主是要运行时动态加载一个库,这个也是没有问题的,OS 提供了相关的 API,很多软件都有类似插件系统一样的东西,最常见的就是各大主流操作系统都支持的驱动和内核扩展——实在不行你自己定义一个格式自己载入也行 ... 做 JIT 都会涉及类似的操作,至于直接载入 native code 的也有,我猜 Chrome 之前搞得什么 NaCl 就是。
只不过现在都去写 JavaScript,扩展需求一般直接写程序解决不编译成 binary (这实际上是更好的方式),才会有楼主的问题——但是讽刺的是,node 里载入 native 库本来就会走同样的一个流程,并且 node 生态是很依赖 native 库的。

(另外用 binary 做扩展还是写代码做扩展,其实更多取决于需求,Solaris DTrace 和 Linux eBPF 这些做 profiling 的工具虽然是内核级的,但都是用户写程序运行时编译然后塞进内核里面跑,甚至可以直接 JIT 成 native code,像 bcc 一类的工具实际上把 eBPF 做成了 kernel 的 WebAssembly,这对于剖析程序行为过程中不断的调试是很有帮助的。做 graphics 的话,调试过程中 shader 都是一个文本塞进去 JIT 的,而且 GPU 并没有统一的 ISA (不仅仅是不同 vendor 之间的区别,同一 vendor 的不同代产品也不一样),不好直接跑 native code。而使用 native code 做扩展,好处是不限语言,性能上限一般更好(虽然会失去做 IPO/PGO 的机会),并且更方便扩展本身代码的保护。
至于 JavaScript 为啥不兴搞 native 扩展,纯属是因为确实需要做 native 扩展的需求太少,就算有点需求,对于大多数人来说做 native 扩展的成本又太高)

第二步是(在上一步已经得到函数指针的情况下)调用对应的函数。这个就涉及到 Data Layout 和 Calling Convention 之类的问题。

需要注意这两步之间的区别,尤其在外部库和程序本身使用同一种语言的情况下,”动态加载动态库“和”动态获取并调用其中的*任意*函数“是两个过程,在讨论实现细节时把它们混在一起说是不合适的。一般使用 C/C++ 作为 host 来实现的插件系统,都是由 host 来寻找并载入一个动态库,之后会固定地调用其中的某个 init 函数(函数名称、签名都是固定的),init 函数再把各种扩展的东西注册到 host 中。这个过程中所有的接口都是 host 早就决定好的,因此不涉及”动态获取并调用其中的*任意*函数“的过程。

为了更好的理解第一步和第二步之间的区别,首先应该理解“一个编程语言调用自己写的库”和“一个编程语言调用 C 写的库”之间的区别。
很多编程语言都有自己钦定的调用(同样是该编程语言写的)外部库的方式——所有那些乱七八糟的模块,包,import 都属于这个范畴。但是它们的共性是都是调用自己写的东西,你在 Java 里面 import 一个包进来,那个包是 JVM Bytecode 格式,你在 Python 里面 import 一个模块,那模块也是 Python 写的。因为是同一个编程语言,同一个编译器实现,所以你能直接用语言原生的方式使用外部库,非常自然,一般这都是最方便的方式。
但是这是静态调用,如果要动态调用外部库,一般需要其他方式。典型的在 Java 里,动态载入 class 需要用反射。(对于解释型语言来说,静态调用和动态调用是有可能统一的,比如 JavaScript 的 require 就是万能的,既可以静态调用也可以动态调用)。不变的是依然需要所调用的模块是使用该语言编写的——这个说法不严格,应该说是符合该语言自身体系标准的,比如在 node 里可以用 require 来调用 native addon,但是这要求 addon 文件自身实现了 addon 的接口,你不能直接编译一个 OpenSSL,然后就在 node 里把它的 .so require 进来,这个需要使用下一种方式。

这里就可以看出来,无论是静态调用和动态调用,你都会使用一种机制来找到对应的库,在库载入进来之后,使用库中函数的过程,就和使用你自己用该语言写的函数是一样的。“找库”和“调函数”是两个正交的东西。

下一种方式,就是在某个编程语言里面调用 C 外部库。
一个编程语言可以不实现任何的模块等调用外部库的方式,却依然是图灵完全的。但是这样的编程语言字啊实际场景中最多只能做到 Hello World,难以回答“JavaScript 也可以写服务器么?”这种问题。所以编程语言要做模块,做包,也即上面所说的“调用同样是该编程语言写的外部库”的机制,并且提供一堆的库,现在你提供了库让 JavaScript 可以写服务器了,但是缺乏常识的萌新们又问出一堆问题:JavaScript 可以写桌面程序么?可以做 IoT 么?可以做韩国女团的人脸识别么?
解决这些问题的终极方案,就是实现一个调用 C 外部库的机制。因为如果一个编程语言能调用 C 库,实际上就相当于 C 有的库它都能有。这样 JavaScript 就不仅能做韩国女团的人脸识别,甚至还能控制火箭发射(以及火箭爆炸),你就直接告诉萌新们“C 能做的我都能做”就可以了。所以任何一个像样的语言,都会有一个调用 C 库的机制。
这个“调用 C 库的机制”也分不同的方式,常见的一种是:用 C 写 binding,和你要调用的库链接到一起,这一般需要依赖于语言实现的具体 API (在 Java 里倒是有标准化的 JNI,但是我觉得不是所有人都把 JNI 当作是自己认知中“Java 语言”这一概念神圣不可分割的一部分)。Python 和 Lua 的 C Binding、Node 的 C++ Binding 都是一个道理。
还有一种是使用语言本身来描述 C 接口,开发者不需要写任何 C 代码。这个可以继续细分,不过区别更加微妙——一些编译型语言可以在编译时静态生成对 C 函数的调用,比如 Go 的 cgo 和 Haskell 的 FFI。编译型语言也可以在运行时进行完全动态的调用,比如 OCaml 的 ctypes。而解释型语言由于没有这个区分,所以这个做得都差不多,典型如 Python 的 cffi,LuaJIT 的 FFI。
(从命名可见,狭义上的 FFI 仅仅指上面最后一段的东西 ...)

在这种场景下,你依然可以选择是“调用其中固定的函数”还是“动态调用任意函数”,对于编译型语言,你还可以选择“编译时链接固定的库”还是“运行时动态载入库”。

这里有两个常见的特例:
一个是 C,对于 C 来说,不存在“调用自己写的库”和“调用 C 写的库”的区别(因为”自己 = C“ ...)。这样所有其他编程语言费了半天功夫实现的编译器接口也好 FFI 接口也好,在 C 里都是 free 的,因为所有 C 库都天然地符合 C 自身的体系,根本不”foreign“。
但是标准 C 仅仅解决了”静态调用外部库“的问题,并没有解决”动态调用“( C 标准根本就和动态库都没关系)。这个就需要用操作系统的动态库 API,结合 libffi。由于 C 的表达能力实在太过捉鸡,所以这个写起来就像在写另外一种语言,尽管调的还是 C 函数。
在这个过程中,操作系统 API 解决的是”动态加载动态库“的问题,libffi 解决的是“动态调用函数的问题”。实际上没人拦着在 c 文件里面写一个函数,然后在同一个 c 文件里面用 libffi 调用它。

另一个是 C++,首先 C++ 与 C 保持了很大的兼容性,也能直接调用 C 库(嘛虽然有个 extern "C"),这样上面说 C 的话,对 C++ 也都成立。C++ 标准也没解决动态调用的问题,所以动态调用 C 库也需要 libffi,但是问题在于动态载入 C++ 库(这个没问题),*并且*动态调用其中的函数 ... 因为
我至今没见过有人做过那么疯狂的事情!
虽然说有无数的语言都不断地打磨自己的 C FFI,但是很少有做“C++ FFI”并且实质上成功的。尽管 C++ 的生态也很丰富,支持调用 C++ 库中的内容(哪怕是个 binding )的好处也很大。
这不仅仅是 C++ 复杂性的问题,很大程度上也是因为 C 实在太过 primitive,几乎相当于所有语言的下限,而 C++ 接口中涉及的概念对于很多编程语言来说就是根本不兼容的(很多语言没有 class ),所以做“C++ FFI”这个事情,很多时候 by definition 就是有问题的(就不说 template 根本没法做)。
所以很多 C++ 库都是库本身用 C++ 写,然后用 C wrap 一下接口,这样所有能调用 C 的语言,也都能调用这个库。
这就是为什么说楼主的问题和 C++ 根本就没有关系。
话又说回来,这里”动态加载 C++ 动态库“其实是没有问题的,问题出在“调用 C++ 动态库中的函数”这一步。

当然上面这些都是上个时代的东西,现在 114 天就可以产生 514 个新的 RPC 框架,而在 polyglot 的世界里,很多 RPC 框架是跨语言的。跨语言的 RPC 框架一般试图提取各种语言数据模型的共性(即:各种语言的下限,或最大公约数),并且使用一个语言无关的 IDL 来描述。比如 COM/DCOM ( literally 也是上个时代的东西 ...)就是使用一个微软扩展过的 IDL,gRPC 使用 Protocol Buffer 等。
IDL 不仅仅 RPC 会用,它可以作为一个抽象层存在于任何跨语言的场景中(只不过现在萌新们只知道 RPC ...)。比如 DOM API 就是语言无关的,DOM API 可以用一种叫 WebIDL 的东西来描述。而浏览器引擎一般都会带这样一份 IDL 定义,然后会实现一个代码生成器,在编译时根据 IDL 生成对应 JavaScript 引擎的 binding,将引擎中的 C++ 接口暴露给 Web 开发者。这个原理和写 node C++ addon 其实是一样的,不过流程要成熟许多,更方便维护。
所以楼主说用 XML 也好 JSON 也罢来描述接口,多少也有点重新造轮子的意思。

@Shazoo 你 assume 了所有代码都是自己控制的,忽略了第三方扩展的需求。并且写 bridge library 并不一定比 FFI 更方便。
很多时候 bridge 需要依赖于编译器的 API,这是编译器的一个实现细节,原则上用户不需要关心。
更别说某些语言的 FFI 只需要一个 C header 就可以帮你把很多事情全做掉,方便的 FFI 恰恰是语言和生态强大的体现,必须写 bridge library,反倒是个问题。
2019-09-28 11:11:55 +08:00
回复了 anhkgg 创建的主题 程序员 教会微信:突破文件发送 100M 限制
楼主这跟微信杠了多久了 ... 都做了个教会专用的版本了
2019-09-28 01:50:11 +08:00
回复了 cskeleton 创建的主题 分享发现 终于找到经常网址复制不全的原因了
@jasonyang9 如果真的是 MS 的人,那么他们强奸一次用户,就会在注册表里面加一个选项能让你回退掉 :)
2019-09-26 21:24:59 +08:00
回复了 taogen 创建的主题 程序员 你们读过计算机四大名著吗?
@scukmh 贵校教 CLRS ?
2019-09-26 21:15:22 +08:00
回复了 ChristopherWu 创建的主题 程序员 看 SICP 不如先看 The Little Schemer
The Little 其实是一个系列,用不上 Scheme 也可以看看别的:
The Little LISPer
The Little MLer
The Little Schemer
The Seasoned Schemer
The Reasoned Schemer
A Little Java, A Few Patterns
The Little Typer
The Little Prover
2019-09-26 21:11:45 +08:00
回复了 jeblur 创建的主题 问与答 想搞一个 manjaro,问题来了
先搞个虚拟机试试吧
桌面 Linux 没有“优秀”的 distro
2019-09-24 01:37:59 +08:00
回复了 mpb 创建的主题 职场话题 校招想进大厂真的好玄学啊,心态都不好了
运气确实很重要。你仔细想想就会发现人生从头到尾都 tm 靠的是运气,所以没必要揪着这一件事折腾。
2019-09-24 01:25:24 +08:00
回复了 PainAndLove 创建的主题 程序员 敲代码的另一种方式?
“键盘+定位设备”这种配器模式有它适用的地方,只不过不是”敲”代码。
普通用户一般会认为有 GUI 的地方就离不了某种定位设备,可能是鼠标、触摸板、触摸,或者手写笔。
程序员知道 Vim,知道 text-based interface,快捷键玩的也溜,但是程序员的问题就在于一般只跟代码和文档打交道,所以楼主尽管有跳出圈子的想法,但是也局限在“敲代码”的边界里面 ...
但是同时不少程序员也玩游戏,玩摄影,做视频,绘画,在进行这些活动的时候,定位设备依然是不可或缺的。可惜的是,这四种活动中你的操作基本是完全随机的 ... 只有做视频跟编程沾边比较多

楼主可以了解下 Visual Programming,在这种形式里面,开发者主要做的不是写代码,而是拼接已有的逻辑和模块。这种方法本质上依赖于 GUI,并且也很大依赖于定位设备。所以之前那些编辑器什么的不管用,一个基本的“IDE”是最低要求。并且如果要做的好用,需要你发挥一点交互功力(再不济也得发挥点抄袭功力)来真正提高这个 IDE 的效率。

举个例子:写一个函数,你得先把签名定下来,参数名和类型写上去,写到一半发现不对要改签名,那你得把光标挪回那行改(如果你写的是 C/C++ 这种那恭喜你要改两次 ...),哪怕你只是做一个 prototype,而在图形化的环境里面,我就只要把“Input Node”拖进来,然后连到需要用这个参数的地方就行了。

这种模式有什么实际应用?我也不是十分清楚,但是如果曾经在基础设施稍微好一点的公司干过的话,应该会见过类似“配置流程”之类的东西,有一点相似之处。给几个 hint:
* 如果目标使用环境本身就属于无法离开定位设备的情况,这种模式有天然的优势( Vim 等文本操作模式的全键盘操作无法实现)。
* 图形化的界面对非程序员(包括且不限于项目中的其他角色以及终端用户)更友好。
* 对没键盘 /键盘残废的触屏设备更友好。(虽然我个人认为这个还是要结合文本编程,也就是说键盘依然是很必要的)
2019-09-15 16:17:33 +08:00
回复了 shachengpo 创建的主题 程序员 程序员终究不是“终身职业”,窝慌了
@justforlook44444 我没说程序员是啊
2019-09-14 23:53:32 +08:00
回复了 shachengpo 创建的主题 程序员 程序员终究不是“终身职业”,窝慌了
@justforlook44444 我觉得在国内的语境下,“终身职业”并不一定包含“越老越值钱”的意思,更多的是“保本”,“稳定”的含义
2019-09-14 22:54:46 +08:00
回复了 shachengpo 创建的主题 程序员 程序员终究不是“终身职业”,窝慌了
我一直觉得习惯“终身职业”的人更适合进体制。任何体制外的工作都不是“终身职业”。
2019-09-14 11:41:39 +08:00
回复了 x97bgt 创建的主题 程序员 怎么提高使用 Windows 的工作效率?
微软最近在做 Win10 的 PowerToys,里面有个东西叫 FancyZones: https://github.com/microsoft/PowerToys/tree/master/src/modules/fancyzones

我不怎么用 Windows,不过看起来这东西能让 Windows 的窗口管理 better than better

至于终端,你暂时需要的是带 Tab 的终端模拟器 + tmux。
一个关键的问题是,无论 Win10 还是 macOS,默认设置下,不按 Win+Tab/Cmd+Tab 的话都是看不见不同窗口的标题名的,在任务栏 /Dock 上只能通过图标分辨窗口(而且 Windows 现在默认也像 mac 一样把多个同样的窗口 collapse 到同一个图标上),这导致一个很影响效率的问题,就是如果同一个应用开了多个同类型的窗口,基本不可能一键切换过去。

这个问题会出现在很多常用软件的常用使用场景中,比如多个浏览器窗口,多个终端窗口,多个 Explorer/Finder 窗口,多个编辑器 /IDE 窗口。多个 Office 窗口,多个 PDF 文件——这些都是非常常见的情况。
但是目前主流桌面操作系统的窗口管理机制,根本就没有为这种情况考虑,甚至人为地将“快速切换多个同类型”窗口的任务变得越来越复杂。(目前的桌面系统实际上更适合于“一个浏览器窗口、一个 Word 窗口、一个 PowerPoint 窗口、一个 Excel 窗口、一个 Outlook 窗口、一个 OneNote 窗口、一个 Skype 窗口”的这种场景)移动操作系统更不用说了,貌似 iPadOS 才刚开始做单个 App 多个实例共存。
我认为,不解决这个问题,那就免谈生产力。

不幸地是,所谓的“现代”桌面系统把这个问题完全推给了应用开发者。于是我们看到浏览器有自己的 Tab 系统,终端模拟器有自己的 Tab 系统,终端模拟器里面还可以嵌一个 Tab 系统,Excel 和 OneNote 有自己的 Tab 系统,文件管理器有自己的 Tab 系统,PDF 阅读器有自己的 Tab 系统,编辑器 /IDE 有自己的 Tab 系统,Photoshop 有自己的 Tab 系统,QQ/微信有自己的 Tab 系统 ...
桌面浏览器在世纪初开始引入 Tab,OS X 10.5 ( 09 年)的 Terminal 有了 Tab,10.9 ( 13 年)的 Finder 有了 Tab。最近的 Windows Terminal 作为 9012 年的产品理所当然一开始就有 Tab。
有报道说微软尝试基于 Edge (老的那个)在 Win10 上加入一个略微更 universal 的 Tab。我记得很久之前的 Windows,Explorer 既可以开本地文件夹也可以开网页,这个有点异曲同工,但或许是我记混了,不过确实有这样的产品——KDE 的 Konqueror 就既可以做文件管理器,也可以做浏览器,还有 Tab,虽然这俩东西应该都是历史了)可惜的是后来又说这个东西暂时不做了。
然后就没了 ...

每个软件独立的 Tab,只有两个好处:Tab 和软件本身的结合更紧密;以及桌面环境的开发者省事了。但是造成的问题:软件开发者需要做更多的工作,视觉上会出现不一致(只要看看 Chrome 的 Tab 改过多少版就知道 ...),功能也非常不一致,以及——至少一大部分常用软件,尽管有加 Tab 的需求,却根本就不支持 Tab。
Windows 的 Explorer 到现在没一个官方的 Tab 系统,这导致我到现在一直觉得 Explorer 是个半残的软件,Finder 则是最好用的 GUI 文件管理器(不考虑 bug 比较多的问题的话 ...)( Finder 另一个 killer feature 是“计算所有大小”)

统一 Tab 的另一个重要好处是 Tab 能像窗口一样被桌面环境统一管理,以及统一的搜索——浏览器和文本编辑器已经在做这件事,tmux、Emacs 早就能做到。不过这个其实没那么常用,“搜索”这个操作的成本还是比较高的。Emacs 生态环境有完善的 buffer 管理机制,包括以搜索为核心的操作逻辑——考虑到你可以把任何东西放进 Emacs 的 buffer 里面,这几乎相当于一个半成品的窗口管理器,但是缺少良好支持的好用的 Tab,我认为是 Emacs 的缺陷——如果我的目标 buffer 没有显示在当前 frame 里面,我就必须调起搜索才能找到,但是换在 vim 里面,可能就是 gt 一下的事情,Tab 在不少情况下有不可替代的作用。
again,据我所知,“现代”桌面操作系统目前只停留在搜索应用的阶段,我觉得我们并不能他们指望在这方面能有什么作为。
2019-09-13 21:32:59 +08:00
回复了 efsg 创建的主题 macOS 求推荐图形化 SSH 工具(mac)
@wsseo 我认为就楼主的需求来看,“图形化 SSH 工具”不是合适的选择,更不需要商业产品
之所以一些人更偏向于某些商业图形化 SSH 工具,而不是 SSHFS,原因可能有很多,我只能做推测
比如他们解决了“方便地传输文件,方便地编辑文件”之外的问题
比如他们有商业支持
比如 SSHFS 的实现存在一些问题
比如网络环境受限
或者仅仅是信息不对称

实在不行,小孩才分对错,大人只看利弊,你满意了吧
Might makes Right,你满意了吧


实在不行我们来讨论 5G 预期中的普及能对 SSHFS 的应用产生什么影响吧
2019-09-13 20:58:11 +08:00
回复了 efsg 创建的主题 macOS 求推荐图形化 SSH 工具(mac)
@wsseo 不,就是因为这种方式从根上就是错的。
2019-09-13 20:56:17 +08:00
回复了 efsg 创建的主题 macOS 求推荐图形化 SSH 工具(mac)
@efsg 您好,vi 和 nano 不喜欢可以尝试下 emacs :)
2019-09-13 20:45:35 +08:00
回复了 efsg 创建的主题 macOS 求推荐图形化 SSH 工具(mac)
楼主的需求无非就是,方便地传输文件,方便地编辑文件,简单来说就是以本地文件的方式操作远程文件
那 SSHFS 就可以了啊

"图形化 SSH 工具"这个东西的存在就是很尴尬的事情,这种工具做得再好也不可能像本地文件系统一样和其他软件一起无缝的互操作,虽然它解决的问题是存在的,但是它选择了错误的层级来解决这个问题。我个人觉得这种工具是没有未来的

(然后话题转进到一个图形化的 SSH 连接工具,可以选择服务器,记忆用户名 ...
2019-09-13 17:37:23 +08:00
回复了 alanlian 创建的主题 C++ 关于 cpp 的 copy-and-swap idiom 的问题
其实应该说,你正确调用 swap 的时候,把 std::swap 重载了
另外 C++20 之前调 std::swap 应该是不会调到你的 swap 去的
2019-09-13 17:18:04 +08:00
回复了 alanlian 创建的主题 C++ 关于 cpp 的 copy-and-swap idiom 的问题
@alanlian 意思类似于:
Q:传输大文件用什么服务最吼?
A:顺丰快递
你感受一下

标准对 overload 的定义:“When two or more different declarations are specified for a single name **in the same scope**, that name is said to be overloaded.”
technically,你在使用 swap 的时候用了 overload resolution 的机制,overload resolution 在决定 candidate set 的时候会考虑 scope 和 ADL。不过 overload resolution 和 overloading 是两回事
1 ... 75  76  77  78  79  80  81  82  83  84 ... 123  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2026 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 36ms · UTC 05:23 · PVG 13:23 · LAX 22:23 · JFK 01:23
Developed with CodeLauncher
♥ Do have faith in what you're doing.